/**
 * 分页组件
 * @param id 分页组件id
 * @param rows 每页显示多少条
 * @param count 总条数
 * @param page 当前第几页
 */
function Pagination(id,datatable){
	this.id = id;
	this.datatable=datatable;
	var $pagination = $('#'+this.id);
	this.$pagination = $pagination;
	this.page = this.defaultPage = $pagination.find('input[name="page"]').val();
	this.rows = this.defaultRows = $pagination.find('#rows').val();
	// Logger.info("common.js => this.rows = " + this.rows);
	// Logger.info("common.js => this.id = " + this.id);
	this.count = this.defaultCount = 0;
}
// 获取总页数
Pagination.prototype.getMaxPage = function(){
	var val = parseInt(this.count/this.rows);
	if(this.count % this.rows != 0){
		val = val+1;
	}
	if(isNaN(this.count % this.rows)){
		val = 0;
		this.$pagination.find('#currentPage').val(0);
		this.$pagination.find('#count').text(0);
	}
	return val;
};
// 重置分页
Pagination.prototype.resetPagination = function(){
	this.page = this.defaultPage;
	this.rows = this.defaultRows;
	this.count = this.defaultCount;
	this.refresh(false);
};
/**
 * 执行查询数据，同时将分页信息刷新到页面上
 * @param query boolean 是否执行查询，默认执行
 */ 
Pagination.prototype.refresh = function(query){
	// 只有当当前页码真实改变时才赋值，否则会触发死循环
	this.$pagination.find('#maxPage').text(this.getMaxPage());
	if(this.$pagination.find('#currentPage').val() != this.page) {
		this.$pagination.find('#currentPage').val(this.page);
	}
	this.$pagination.find('#rows').val(this.rows);
	this.$pagination.find('#count').text(this.count);
	
	query = (query == undefined || query)?true:query;
	query && this.datatable && this.datatable.getAjax().send(false);
};
/**
 * 页码改变时触发
 * @param option 操纵页码改变的因素
 */
Pagination.prototype.pageChanged = function(option) {
	switch(option){
	case 'homePage': // 首页
		this.page=1;
		break;
	case 'endPage': // 最后一页
		this.page=this.getMaxPage();
		break;
	case 'nextPage': // 下一页
		if(this.page == this.getMaxPage()){
			new $.zui.Messager("提示：已经是最后一页了",{
				type:'info',
				time:2000,
				placement:'top'
			}).show();
		}
		if(this.page < this.getMaxPage()) {
			this.page++;
		}
		break;
	case 'prevPage': // 上一页
		if(this.page == 1){
			new $.zui.Messager("提示：已经是第一页了",{
				type:'info',
				time:2000,
				placement:'top'
			}).show();
		}
		if(this.page>1){
			this.page--;
		}
		break;
	case 'rowsChanged': // 总页数改变
//		this.resetPagination();
		this.rows = this.$pagination.find('#rows').val();
		break;
	case 'currentPage': // 当前页码输入时改变
		var currentPage = this.$pagination.find('#currentPage').val();
		
		// 校验输入合法性，输入的值必须是大于等于1且小于最大页码数的整数值
		var type = /^[0-9]*[0-9][0-9]*$/;
	    var re = new RegExp(type);
		if( currentPage.match(re)!=null){
			currentPage = parseInt(currentPage);
			if(currentPage >= 1 && currentPage <= this.getMaxPage()){
				this.page = currentPage;
			}
		}
		break;
	}
	this.refresh();
};

/////////////////////////////////////////
//  对话框
/////////////////////////////////////////
function MsgDialog(){
	var buttonId = "dialogtriggerButton";
	this.$triggerButton = this._buildTriggerButton(buttonId);
}
//根据弹出对话框的不同，设置不同的样式
MsgDialog.prototype.styles={
	success:{
		icon:'icon-ok-sign', // 图标
		style:'alert-success', // 样式
		defaultTitle:'成功' // 默认标题
	},
	error:{
		icon:'icon-remove-sign',
		style:'alert-danger',
		defaultTitle:'错误'
	},
	info:{
		icon:'icon-info-sign',
		style:'alert-primary',
		defaultTitle:'信息'
	},
	warn:{
		icon:'icon-warning-sign',
		style:'alert-warning',
		defaultTitle:'警告'
	},
	confirm:{
		icon:'icon-question-sign',
		style:'alert-primary',
		defaultTitle:'确认'
	}
};
MsgDialog.prototype.getBody = function() {
	return $(top.document.body);
};
/**
 * 打开子页面，目前仅支持在top下的一级iframe打开子窗口，二级以上的iframe虽然能打开，但不能与上一级窗口交互
 * @param name 对话框的id，必须
 * @param title 标题，必须
 * @param url 要打开的链接，必须
 * @param width 宽度 单位：px/em
 * @param height 高度 单位：px/em
 * @param size 设置窗口的大小。使用了此参数，width和height会被忽略，默认：'',可选值：'lg'/大对话框,'sm'/小对话框,'fullscreen'/全屏显示
 * @param icon 对话框标题图标，要设置ZUI的字体图标，如:书/book,相机/camera
 * @param type 窗口类型 ajax/iframe,默认为ajax
 * @param fade 是否使用淡入淡出动画
 */
MsgDialog.prototype.open=function(name,title,url,width,height,resize,size,icon,type,fade){
	// 设置相关属性
	var $triggerButton = this._buildTriggerButton("trigger_btn_"+name);
	// 移除已经存在的对话框
	this.getBody().find("#" + name + " .modal").remove();
	$triggerButton.attr({
						"data-url":url,
						"data-type":type || 'ajax',
						"data-width":width || '',
						"data-height":height || '',
						"data-resize":resize || '',
						"data-icon":icon || '',
						"data-size":size||'',
						"data-name":name,
						"data-backdrop":"static",
						"data-fade": (fade == undefined ? true : fade),
						"data-loadingIcon":"icon icon-spin icon-spinner-indicator"
					})
				.text(title);
	var getIframeId = function() {
		var iframeId = null;
		var mWindow = window;
		$(top.document.body).find("iframe").each(function(){
			var fid = $(this).data("id");
			if (this.contentWindow == mWindow) {
				iframeId = fid;
			};
		});
		return iframeId;
	};
	var iframeId = getIframeId();
	if (!StringUtil.isEmpty(iframeId)) {
		$triggerButton.attr("data-iframe-id", iframeId);
	}
	$triggerButton.click();
	$triggerButton.remove();
};
/**
 * 弹出模态框
 * @param name 对话框的id，必须
 * @param title 标题，必须
 * @param dialog 要弹出的模态框的查询字符串，如:"#MyModal"
 */
MsgDialog.prototype.trigger = function(name,title,dialog){
	var $triggerButton = this._buildTriggerButton("trigger_btn_" + name);
	$triggerButton.attr({
						"data-toggle":"modal",
						"data-target":dialog,
						"data-backdrop":"static",
						"data-name":name
					})
				.text(title);
	$triggerButton.click();
	$triggerButton.remove();
};
/*
 * 构造事件触发按钮
 */
MsgDialog.prototype._buildTriggerButton = function(buttonId){
	// 对话框触发按钮
	var triggerButton = top.document.getElementById(buttonId);
	var $triggerButton;
	if(triggerButton == null){
		$triggerButton = $("<button></button>").prop("id",buttonId)
									.attr("data-toggle","modal")
									.attr("data-moveable","true")
									.attr("hidden","hidden");
		this.getBody().append($triggerButton);
	} else {
		$triggerButton = $(triggerButton);
	}
	return $triggerButton;
};
/**
 * 弹出警告提示
 * @param msg 警告信息
 * @param title 标题
 * @param okfunc 关闭时的回调函数
 */
MsgDialog.prototype.warn=function(msg,title,okfunc){
	this._buildDialog('warn',msg, title, okfunc);
	
};
/**
 * 弹出信息提示
 * @param msg 提示信息
 * @param title 标题
 * @param okfunc 关闭时的回调函数
 */
MsgDialog.prototype.info = function(msg,title,okfunc){
	this._buildDialog('info',msg, title, okfunc);
};
/**
 * 信息确认对话框
 * @param msg
 * @param title
 * @param okfunc
 * @param cancelFunc
 */
MsgDialog.prototype.confirm = function(msg,title,okfunc,cancelFunc){
	this._buildDialog('confirm',msg, title, okfunc,cancelFunc);
};
/**
 * 提示操作成功
 * @param msg 成功提示信息
 * @param title 标题
 * @param okfunc 关闭时的回调函数
 */
MsgDialog.prototype.success = function(msg,title,okfunc){
	this._buildDialog('success',msg, title, okfunc);
	
};
/**
 * 错误提示
 * @param msg 错误信息
 * @param title 标题
 * @param okfunc 关闭时的回调函数
 */
MsgDialog.prototype.error = function(msg,title,okfunc){
	this._buildDialog('error',msg, title, okfunc);
};
/**
 * 构造对话框
 * @param type 对话框类型
 * @param msg 对话框要显示的信息
 * @param title 标题
 * @param okfunc 关闭时的回调
 */
MsgDialog.prototype._buildDialog = function(type,msg,title,okfunc,cancelFunc){
	var style = this.styles[type]; // 根据对话框类型选择样式
	
	var dialog = this.getBody().find("#" + type)[0]; // 查找是否已经存在与type同名的dialog
	var $dialog;
	if(dialog == null){
		// 拼接对话框的html代码
		var $html = $("<div class='modal fade' tabindex='-1' style='z-index:1600' data-dialog='true' role='dialog' aria-hidden='true' data-backdrop='static' data-appendToBody='true'>"
			+ "<div class='modal-dialog '>"
				+ "<div class='modal-content'>"
					+ "<div class='modal-header'>"
						+ "<button type='button' class='close' data-dismiss='modal'><span aria-hidden='true'>&times;</span><span class='sr-only'>Close</span></button>"
						+ "<h4 class='modal-title' id='modal-title'></h4>"
					+ "</div>"
					+ "<div class='modal-body'>"
						+ "<div class='alert with-icon' id='style'>"
						+ "<i id='icon'></i>"
						+ "<div class='content' style='word-wrap:break-word;word-break:break-all'>"
							+ "<strong id='content'></strong>"
						+ "</div>"
					+ "</div>"
				+ "</div>"
				+ "<div class='modal-footer'>"
					+ "<button type='button' class='btn btn-primary' data-dismiss='modal' data-id='ensure'>确定</button>"
				+ "</div>"
			+ "</div>"
			+ "</div>"
		+ "</div>");
		$html.attr('id',type);
		
		this.getBody().append($html);
		$dialog = this.getBody().find("#"+type);
	} else {
		$dialog = $(dialog);
	}
	$dialog.find('#modal-title').text(title || style.defaultTitle);
	$dialog.find("#style").prop("class","alert "+style.style+" with-icon");
	$dialog.find("#icon").prop("class",style.icon);
	/*$dialog.find("#content").text(msg?msg:'');*/
	$dialog.find("#content").html(msg?msg:'');
	// 绑定事件
	$dialog.off('click',"button[data-id='ensure']")
			.on('click',"button[data-id='ensure']",function(e){
				MsgBox.getCurrentOpenDialogWindow().setTimeout(function(){
					okfunc && okfunc();
					$dialog.off('click',"button[data-id='ensure']");
				}, 500);
			});
	if(type=='confirm') {
		if($dialog.find(".modal-footer>button[data-id='cancel']").length==0){
			$dialog.find(".modal-footer").append("<button type='button' class='btn btn-default' data-dismiss='modal' data-id='cancel'>取消</button>");
		}
		$dialog.off('click',"button[data-id='cancel']")
				.on('click',"button[data-id='cancel']",function(e){
					cancelFunc && cancelFunc();
					$dialog.off('click',"button[data-id='cancel']");
				});
	}
	this.$triggerButton = this._buildTriggerButton("triggerBtn_" + type);
	this.$triggerButton.attr("data-target","#" + type);
	this.$triggerButton.click();
};
/**
 * 实例：防止暴力点击
 * @param msg
 * @param key
 * @param time
 * @param openDialog default:true
 * @return true:已阻止，false:未阻止
 * @autor lj
 */
MsgDialog.prototype.preventViolentClick = function(key,msg,time,openDialog){
	if(!key){
		Logger.error("阻止暴力点击的key值是必须的");
		return false;
	}
	msg = msg || "请不要频繁点击";
	time = time || 500; // 默认500ms
	openDialog = openDialog==undefined?true:openDialog;
	
	var lastTimestamp = $.zui.store.get(key) || 0;
	Logger.debug("common.js MsgDialog.preventViolentClick lastTimestamp => " + lastTimestamp);
	var currTimestamp = new Date().getTime();
	Logger.debug("common.js MsgDialog.preventViolentClick currentTimestamp => " + currTimestamp);
	Logger.debug("common.js MsgDialog.preventViolentClick 时间差 => " + (currTimestamp-lastTimestamp));
	$.zui.store.set(key,currTimestamp);
	
	var prevent = !(currTimestamp - lastTimestamp > time);
	Logger.warn("common.js preventKey => " + key +", prevent => " + prevent);
	if(prevent && openDialog) MsgBox.info(msg);
	return prevent;
};
/**
 * 关闭当前活动的对话框
 */
MsgDialog.prototype.closeActiveDialog = function(){
	this.getBody().find(".modal[aria-hidden='false']").each(function(){
		var $closeButton = $(this).find("*[data-dismiss='modal']");
		$closeButton.filter('.close').click();
	});
};
/**
 * 启动加载中状态，屏蔽用户事件
 */
MsgDialog.prototype.startLoading = function(){
	Logger.debug("common.js startLoading=> 启动加载中状态，屏蔽用户事件");
	var $loadingDialog = this.getBody().find("div#msg_dialog_loading");
	if(!$loadingDialog.length){
		$loadingDialog = $("<div>").attr({
			'id':'msg_dialog_loading',
			'class':'page-loading',
			'data-loadingLevel':0
		});
		$loadingDialog.css('display','none'); // 默认不显示
		var $loadingIcon = $("<i>").attr("class","icon icon-spin icon-spinner-indicator icon-3x");
		$loadingDialog.append($loadingIcon);
		this.getBody().append($loadingDialog);
	}
	var loadingLevel = $loadingDialog.attr('data-loadingLevel');
	$loadingDialog.attr('data-loadingLevel',parseInt(loadingLevel)+1); // 调用一次startLoading，loadingLevel+1
	$loadingDialog.css("display",'block');
	Logger.debug('common.js startLoading => loadingLevel => ' + loadingLevel);
};
/**
 * 关闭加载中状态
 */
MsgDialog.prototype.stopLoading = function(){
	Logger.debug("common.js stopLoading=> 关闭加载中状态");
	
	var $loadingDialog = this.getBody().find("div#msg_dialog_loading");
	if(!$loadingDialog.length){
		return ;
	}
	var loadingLevel = $loadingDialog.attr('data-loadingLevel');
	$loadingDialog.attr('data-loadingLevel',parseInt(loadingLevel)-1); // 调用一次startLoading，loadingLevel+1
	if(loadingLevel-1 <= 0) {
		$loadingDialog.css('display','none');
		$loadingDialog.attr('data-loadingLevel',0);
	}
	Logger.debug('common.js stopLoading => loadingLevel => ' + loadingLevel);
};
/**
 * 获取当前打开对话框的window对象
 * 目前仅支持获取top下一级iframe的window
 */
MsgDialog.prototype.getCurrentOpenDialogWindow = function() {
	//var frameId = this.getBody().find(".modal[aria-hidden='false']:not([data-dialog='true'])").data("iframe-id");
	var frameId = this.getBody().find("#pageContent>.f-tabset").find("li.active").data("id");
	var mWindow = null;
	this.getBody().find("iframe").each(function(){
		if ($(this).data("id") == frameId) {
			mWindow = this.contentWindow;
		}
	});
	if (mWindow == null) {
		mWindow = window;
	}
	return mWindow;
	
};

/**
 * 获取当前打开对话框的window对象
 * 目前仅支持获取top下一级iframe的window
 */
MsgDialog.prototype.getCurrentOpenDialogWindow = function() {
	var frameId = this.getBody().find(".modal[aria-hidden='false']:not([data-dialog='true'])").data("iframe-id");
	var mWindow = null;
	this.getBody().find("iframe").each(function(){
		if ($(this).data("id") == frameId) {
			mWindow = this.contentWindow;
		}
	});
	if (mWindow == null) {
		mWindow = window;
	}
	return mWindow;
	
};

// MsgDialog定义完成后，实例化一个MsgDialog对象
window.MsgBox = new MsgDialog();

/**
 * 封装 Ajax 请求
 * @param url
 * @param method post/get 默认:get 同ajax的type
 * @param data 请求参数
 * @param dataType json/xml
 * @param async 同步异步 值：true/false
 * @param timeout 超时时间
 * @param cache boolean 设置是否从浏览器缓存中加载请求信息
 * @param silent 是否在不影响用户操作情况下发送ajax，默认为false
 * @param autoSend 是否自动发送
 * @author lj
*/
function CommonAjax(url,method,data,dataType,async,timeout,cache,silent,autoSend) {
	this.url=url;
	this.method=method;
	this.data=data;
	this.dataType = dataType || 'json';
	this.async = async == undefined || async ? true : false;
	this.timeout = timeout;
	Logger.debug("common.js => CommonAjax constructor timeout parameter =>" + timeout);
	this.cache = cache==undefined || cache ? cache : false;
	this.silent = silent || false;
	this.contentType = 'application/json';
	this.autoSend = autoSend;
}
CommonAjax.prototype.setContentType = function(contentType){
	this.contentType = contentType;
};
CommonAjax.prototype.setUrl = function(url){
	this.url = url;
};
CommonAjax.prototype.getUrl = function(){
	return this.url;
};
/**
* 注册当ajax请求成功时调用的方法，该方法有三个参数，分别对应ajax请求成功的三个参数：data,status,xhr
* @param succFunc ajax请求响应成功后调用的函数
*/
CommonAjax.prototype.bindSuccessEvent = function(succFunc){
	this.succFunc = succFunc;
};
/**
 * 注册当ajax请求业务错误时调用的方法，该方法有三个参数，分别对应ajax请求成功的三个参数：data,status,xhr
 * @param succFunc ajax请求响应成功后调用的函数
 */
CommonAjax.prototype.bindServiceError = function(serviceErrFunc){
	this.serviceErrFunc = serviceErrFunc;
};
/**
* 注册当ajax请求失败时调用的方法，该方法有三个参数，分别对应ajax请求失败的三个参数：xhr,textStatus,errorThrown
* @param errorFunc ajax请求响应失败后调用的函数
*/
CommonAjax.prototype.bindErrorEvent = function(errorFunc){
	this.errorFunc = errorFunc;
};
/**
 * 发送ajax之前调用的函数
 * @param beforeSendFunc
 * @author lj
 */
CommonAjax.prototype.bindBeforeSendEvent = function(beforeSendFunc) {
	this.beforeSendFunc = beforeSendFunc;
};
/**
 * ajax 的 complete function
 * @param complete
 * @author lj
 */
CommonAjax.prototype.bindCompleteSendEvent = function(completeFunc) {
	this.completeFunc = completeFunc;
};
CommonAjax.prototype.getSetting = function(){
	var _this = this;
	var data = {
		'type' : _this.method==null ? undefined : _this.method,
		'url' : _this.url,
		'data' : _this.data,
		'dataType' :_this.dataType,
		'success':function(data,status,xhr){
			$.sessionTimeoutHandle(xhr, status);
			if(!data){
				Logger.debug("common.js => CommonAjax.getSetting data.success => ajax 没有返回任何数据！");
				return ;
			}
			if(data.success==false || data.success == 'false'){ // data 中可能没有 isSuccess 属性
				var message = data.message || "系统错误";
				if (data.code == "0000") {
					_this.serviceErrFunc || MsgBox.error(data.message);
				}
				_this.serviceErrFunc && _this.serviceErrFunc(data,status,xhr);
				Logger.error("ajax send error , message: " + message);
				return ;
			}
			try{
				_this.succFunc && _this.succFunc(data,status,xhr);
			}catch(e){
				Logger.error("common.js => CommonAjax.getSetting data.success => 执行用户的success回调方法失败 e.message = " + e.stack);
			}
		},
		'error':function(xhr,textStatus,errorThrown){
			$.sessionTimeoutHandle(xhr, status);
			if (!xhr.hasDone) {
				MsgBox.error("访问服务器失败");
			}
			try{
				_this.errorFunc && _this.errorFunc(xhr,textStatus,errorThrown);
			}catch(e){
				Logger.error("common.js => CommonAjax.getSetting data.error => 执行用户的error回调方法失败 e.message = " + e.message);
			}
		},
		'async':_this.async,
		'timeout':parseInt(_this.timeout),
		'beforeSend':function(xhr){
			if(!_this.silent)
				MsgBox.startLoading();
			try{
				_this.beforeSendFunc && _this.beforeSendFunc(xhr);
			}catch(e){
				Logger.error("common.js => CommonAjax.getSetting data.beforeSend => 执行用户的beforeSend回调方法失败 e.message = " + e.message);
			}
		},
		'complete':function(xhr,textStatus){
			$.sessionTimeoutHandle(xhr, textStatus);
			Logger.debug("common.js => CommonAjax.getSetting => complete _this.silent = "  +_this.silent);
			if(!_this.silent)
				MsgBox.stopLoading();
			_this.completeFunc && _this.completeFunc(xhr,textStatus);
		},
		'cache':_this.cache,
//		'contentType':'application/json'
		'contentType':_this.contentType
	};
	// Logger.info("common.js 发送ajax请求的data => " + JSON.stringify(data));
	return data;
};
/**
 * 发送aja请求
 * @author lj
 */
CommonAjax.prototype.send = function(){
	Logger.info("正在发送Ajax ,ajax info => " + JSON.stringify(this));
	$.ajax(this.getSetting());
	this.urlRestore();
};
/**
 * 通过addParam 添加data参数
 * @param key 
 * @param value 值
 * @author lj
 */
CommonAjax.prototype.addParam = function(key,value){
	if(this.data==undefined)
		this.data={};
	this.data[key] = value;
};
/**
 * 直接性的为ajax赋值参数
 * @param data ajax请求参数
 */
CommonAjax.prototype.setData = function(data){
	this.data = data;
};
/**
 * 出于对restful风格的考虑，新增临时url方法。值得注意的是，此方法一经调用，
 * 必须调用send方法以还原url，不然需要手动调用urlRestore方法进行还原
 * @param func func必须有最新url返回，func带一个url参数，是原始url
 */
CommonAjax.prototype.tempUrl = function(func) {
	this.oUrl = this.url;
	var tUrl = func(this.url);
	this.url = tUrl;
};
/**
 * URL还原
 */
CommonAjax.prototype.urlRestore = function() {
	if (this.oUrl) {
		this.url = this.oUrl;
		this.oUrl = null;
	}
};
//////////////////////////
// AjaxForm
//////////////////////////
AjaxForm.prototype = new CommonAjax(); // 继承自CommonAjax
/**
 * Ajax表单提交组件
 * @param frm 表单查询字符串，例："#xxx" 必须
 * @param 数据类型 json/xml,同发送ajax请求的dataType，默认为'json'
 * @param async 同步异步 值：true/false
 * @param timeout 超时时间
 * @param cache boolean 设置是否从浏览器缓存中加载请求信息
 * @param autoSend 是否自动发送
 * @author lj
 */
function AjaxForm(frm,url,method,data,dataType,async,timeout,cache,silent,autoSend){
	this.frm = frm;
	this.url = url;
	this.method = method;
	this.data = data;
	this.dataType = dataType || 'json';
	this.async = async == undefined || async ? true : false;
	this.timeout = timeout;
	this.cache = cache==undefined || cache ? cache : false;
	
	this.hasPrepare = false; // 是否事先准备ajax
	this.silent = silent || false;
	this.autoSend = autoSend;
};
/**
 * 准备ajax请求
 */
AjaxForm.prototype.prepare = function(){
	// this.hasPrepare=true;
	var _this = this;
	
	// 组装要发送的数据，1.将form中的数据序列化，2.将this.data中的数据加入到frmData中，最终发送ajax请求时，传递的参数为frmData
	var frmData = $(this.frm).serializeObject();
	if(_this.data!=undefined){
		$.each(_this.data,function(_key,_value){
			frmData[_key]=_value;
		});
	}
	var getOption = function(mType){
		return {
			'url':_this.url,
			'type':_this.method,
			'data':mType?_this.data:frmData,
			'dataType':_this.dataType,
			'success':function(data,status,xhr){
				$.sessionTimeoutHandle(xhr, status);
				if(!data){
					Logger.debug("common.js => AjaxForm.AjaxForm success => ajax 没有返回任何数据！");
					return ;
				}
				if(data.success == false || data.success == "false"){
					var message = data.message || "系统错误";
					if (data.code == "0000") {
						_this.serviceErrFunc || MsgBox.error(data.message);
					}
					_this.serviceErrFunc && _this.serviceErrFunc(data,status,xhr);
					Logger.error("ajax send error , message: " + message);
					return ;
				}
				try{
					_this.succFunc && _this.succFunc(data,status,xhr);
				}catch(e){
					Logger.error(e);
				}
			},
			'error':function(xhr,textStatus,errorThrown){
				$.sessionTimeoutHandle(xhr, status);
				if (!xhr.hasDone) {
					MsgBox.error("访问服务器失败");
				}
				Logger.error("访问服务器失败, xhr: "+JSON.stringify(xhr)+", textStatus: " + textStatus + ", errorThrow: "+errorThrown);
				try{
					_this.errorFunc && _this.errorFunc(xhr,textStatus,errorThrown);
				}catch(e){
					Logger.error("common.js => AjaxForm.prepare data.error => 执行用户的 error 回调方法失败 e.message = " + e.message);
				}
			},
			'async':_this.async,
			'timeout':_this.timeout,
			'cache':_this.cache,
			'beforeSend':function(xhr){
				if(!_this.silent)
					MsgBox.startLoading();
				try{
					_this.beforeSendFunc && _this.beforeSendFunc(xhr);
				}catch(e){
					Logger.error("common.js => AjaxForm.prepare data.beforeSend => 执行用户的 beforeSend 回调方法失败 e.message = " + e.message);
				}
			},
			'complete':function(xhr,textStatus){
				$.sessionTimeoutHandle(xhr, textStatus);
				if(!_this.silent)
					MsgBox.stopLoading();
				_this.completeFunc && _this.completeFunc(xhr,textStatus);
			}
		};
	};
	$(this.frm).ajaxFormUnbind();
	$(this.frm).ajaxForm(getOption(true));
	return getOption();
},
/**
 * 发送Ajax请求
 * @param hasPrepare 是否准备ajax
 */
AjaxForm.prototype.send = function(){
	var mOption = this.prepare();
	Logger.info("正在发送Ajax ,ajax info => " + JSON.stringify(mOption));
	// 触发表单提交
//	if($(this.frm).find("#formSubmit").length==0){
//		 $(this.frm).append("<button hidden='hidden' type='submit' id='formSubmit'></button>");
//	}
//	$(this.frm).find("#formSubmit").click();
//	$(this.frm).ajaxSubmit();
//	this.data=null; // 发送完ajax请求后，将请求参数清空
	$.ajax(mOption);
	this.urlRestore();
};

////////////////////////////////////
// 树
////////////////////////////////////

/**
 * 树
 * @param treeId 树的id
 * @param keys ztree树中定义的字段名称与具体业务字段名称间的对应关系，有这么几个字段：name,url,title,checked,children
 * @author lj
 */
function Tree(treeId,keys){
	this.id = treeId;
	this.keys = keys;
	this.recorder = new Recorder();
	this.onCurrentNodeSelected = null; // 当选中某个节点时触发的事件
}
/**
 * 设置最大层级，-1表示无限制
 */
Tree.prototype.setMaxLayer = function(maxLayer) {
	if (StringUtil.isEmpty(maxLayer)) {
		maxLayer = -1;
	}
	this.maxLayer = maxLayer;
};
Tree.prototype.getMaxLayer = function() {
	return this.maxLayer;
};
/**
 * 刷新
 */
Tree.prototype.refresh = function(){
	var treeObj = $.fn.zTree.getZTreeObj(this.id);
	treeObj.refresh();
};
/**
 * zh 新增子节点
 */
Tree.prototype.addNode = function(node){
	// 组装节点信息
	var childNode = new Object();
	var newNodeId = new UUID().toString();
	childNode[this.keys.id] = newNodeId;
	childNode[this.keys.name] = "新节点";
	childNode['id']=newNodeId;
	// 向ztree中增加了新的节点后，返回当前节点及其子节点
	var newNodes = null; 
	var treeObj = $.fn.zTree.getZTreeObj(this.id);
	if(node==null) { // 传入null，那么新增根节点
		newNodes = treeObj.addNodes(null, childNode);
	}else{
		if(!node[this.keys.id]) { // 选中节点没有id
			Logger.error("你所选中的节点id值为 null");
			return {};
		}
		var parentId = node[this.keys.id];
		childNode[this.keys.pid] = parentId;
		var parentZNode = node;
		if (parentZNode.level >= (this.maxLayer-1) && this.maxLayer != -1) {
			$.messager.info('添加新节点失败，你最多可以添加到第' + this.maxLayer + '级');
			return {};
		}
		newNodes = treeObj.addNodes(parentZNode, childNode, true); // 得到新增加的节点
	}
	// 选中新增加的节点
	treeObj.selectNode(newNodes[0]); 
	this.recorder.getNewRecords().put(newNodes[0]);
	Logger.info("你正在新增ztree节点，新增的节点："+JSON.stringify(newNodes));
	return newNodes[0];
};
/**
 * 新增子节点--old
 */
//Tree.prototype.addNode = function(){
//	// 组装节点信息
//	var childNode = new Object();
//	var newNodeId = new UUID().toString();
//	/*childNode['id'] = newNodeId;*/
//	childNode[this.keys.id] = newNodeId;
//	childNode[this.keys.name] = "新节点";
//	
//	// 向ztree中增加了新的节点后，返回当前节点及其子节点
//	var newNodes = null; 
//	
//	var treeObj = $.fn.zTree.getZTreeObj(this.id);
//	var nodes = treeObj.getSelectedNodes();
//	if(nodes[0]==null) { // 没有选择节点，那么新增根节点
//		newNodes = treeObj.addNodes(null, childNode);
//	}else{
//		if(/*!nodes[0].id*/!nodes[0][this.keys.id]) { // 选中节点没有id
//			Logger.error("你所选中的节点id值为 null");
//			return {};
//		}
//		/*var parentId = nodes[0].id;
//		childNode['pId'] = parentId;*/
//		var parentId = nodes[0][this.keys.id];
//		childNode[this.keys.pid] = parentId;
////		var parentZNode = treeObj.getNodeByParam("id", parentId, null); // 获取父节点
//		var id = this.keys.id;
//		var parentZNode = treeObj.getNodeByParam(id, parentId, null); // 获取父节点
//		newNodes = treeObj.addNodes(parentZNode, childNode, true); // 得到新增加的节点
//	}
//	
//	// 选中新增加的节点
//	treeObj.selectNode(newNodes[0]); 
//	Logger.info("你正在新增ztree节点，新增的节点："+JSON.stringify(newNodes));
//	return newNodes[0];
//};
/**
 * 删除节点
 * @param node
 */
Tree.prototype.removeNode = function(node) {
	if(node && node[this.keys.id]) {
		this.recorder.getDeleteRecords().put(node);
		this.getZTreeObj().removeNode(node);
		return true;
	}
	Logger.warn("删除节点失败： node: " +JSON.stringify(node));
	return false;
	
};
Tree.prototype.cancelAllSelectedNodes = function(){
	this.getZTreeObj().cancelSelectedNode();
};
// 待测
Tree.prototype.cancelSelectedNode = function(node){
	node && this.getZTreeObj().cancelSelectedNode(node);
};
/**
 * 得到当前选中的节点
 * @returns 当前选中的节点
 */
Tree.prototype.getCurrentNode = function() {
	var nodes = this.getSelectedNodes();
	return nodes[0];
};
/**
 * 获取当前选中的节点对象数组
 * @returns
 */
Tree.prototype.getSelectedNodes = function(){
	var treeObj = $.fn.zTree.getZTreeObj(this.id);
	var nodes = treeObj.getSelectedNodes();
	return nodes;
};
/**
 * 获取所有节点，树形结构（第一级节点为根节点）
 * @return Array 所有节点
 */
Tree.prototype.getNodes = function(){
	var treeObj = this.getZTreeObj();
	var nodes = treeObj.getNodes();
	return nodes;
};
Tree.prototype.findNodeById = function(id) {
	/*this.keys.nodeId*/
	var treeObj = this.getZTreeObj();
	var nodes = treeObj.getNodes();
	return this._findNodeById(nodes, this.keys.id, this.keys.children, id);
};
/**
 * 根据id选中节点
 */
Tree.prototype.selectNodeById = function(id) {
	this.selectNode(this.findNodeById(id));
};
/**
 * 根据id查找节点
 */
Tree.prototype._findNodeById = function(nodes,idKey,childrenKey,id) {
    for(var i=0; i < nodes.length; i++){
        var item = nodes[i];
        var tItem = this._findNodeById(item[childrenKey],idKey,childrenKey,id);
        if (tItem != null) {
            return tItem;
        }
        if (item[idKey] == id) {
            return item;
        }
    }
    return null;
};
/**
 * flag==true:表示获取勾选节点
 * flag==false:表示获取未勾选节点
 */
Tree.prototype.getCheckNodes = function(flag){
	var treeObj = $.fn.zTree.getZTreeObj(this.id);
	flag == (flag=="false"||flag==false)?false:true;
	return treeObj.getCheckedNodes(flag);
};
/**
 * 设置需选中节点
 * checked = true 表示勾选节点 默认
 * checked = false 表示节点取消勾选
 * checkTypeFlag = true 表示按照 setting.check.chkboxType 属性进行父子节点的勾选联动操作 
 * checkTypeFlag = false 表示只修改此节点勾选状态，无任何勾选联动操作 默认
 * callbackFlag = true 表示执行此方法时触发 beforeCheck & onCheck 事件回调函数
 * callbackFlag = false 表示执行此方法时不触发事件回调函数 默认
 */
Tree.prototype.setCheckNode = function(nodeArr,checked,checkTypeFlag,callbackFlag){
	checked == (checked=="false"||checked==false)?false:true;
	checkTypeFlag == (checkTypeFlag=="true"||checkTypeFlag==true)?true:false;
	callbackFlag == (callbackFlag=="true"||callbackFlag==true)?true:false;
	var treeObj = $.fn.zTree.getZTreeObj(this.id);
	treeObj.checkAllNodes(false);
	if(nodeArr != undefined && nodeArr != null){
		for(var i=0;i<nodeArr.length;i++){
			var node = treeObj.getNodeByParam(this.keys.id,nodeArr[i][this.keys.id],null);
			treeObj.checkNode(node,checked,checkTypeFlag,callbackFlag);
		}
	}
};
/**
 * 设置选中或取消所有节点
 * @param flag false->取消所有勾选
 * 				true->勾选所有 默认
 */
Tree.prototype.checkAllNodes = function(flag){
	flag = (flag == "false" || flag == false)?false:true;
	var treeObj = $.fn.zTree.getZTreeObj(this.id);
	treeObj.checkAllNodes(flag);
};
//展开所有节点
Tree.prototype.expandAll = function(){
	var treeObj = $.fn.zTree.getZTreeObj(this.id);
	treeObj.expandAll(true);
};
/**
 * 获取ZTree对象
 * @returns
 */
Tree.prototype.getZTreeObj = function(){
	return $.fn.zTree.getZTreeObj(this.id);
};
Tree.prototype.getJsonArrayOfNodes = function(){
	var treeObj = $.fn.zTree.getZTreeObj(this.id);
	var nodes = treeObj.transformToArray(treeObj.getNodes());
	var jsonArr = JSON.stringify(nodes);
	Logger.info(jsonArr);
	return jsonArr;
};
/**
 * 更新一个节点
 * @param node
 * @param refresh default = true
 */
Tree.prototype.updateNode = function(node,refresh){
	var zTree = this.getZTreeObj();
	refresh = refresh ==undefined ? true: refresh;
	zTree.updateNode(node, refresh);// 执行内容更改
	this.recorder.getUpdateRecords().put(node);
};

/**
 * 将ZTree 的nodes实例转为你所需要的nodes
 * @returns {Array}
 */
Tree.prototype.getZTreeNodesToTemplates=function(){
	var treeObj = $.fn.zTree.getZTreeObj(this.id);
	var nodes = treeObj.transformToArray(treeObj.getNodes());
	var arr = new Array();
	
	var _this = this;
	$.each(nodes,function(index,item){
		var nodeIndex = treeObj.getNodeIndex(item); // 当前节点在同级节点中的第几个节点
		var template = _this.converNodeToTemplate(item,nodeIndex);
		arr.push(template);
	});
	return arr;
};

/**
 * 将ztree节点转为你所需要的节点
 * @param node
 * @param index 当前节点在同级节点中的顺序
 * @returns
 * @author lj
 */
Tree.prototype.converNodeToTemplate=function(node,index){
	return node;
};
/**
 * 选中节点
 * @param node 节点对象，请务必保证此节点数据对象 是 zTree 内部的数据对象
 * @param addFlag true:表示追加选中，会出现多点同时被选中的情况
 * 		,false表示单独选中，原先被选中的节点会被取消选中状态
 */
Tree.prototype.selectNode = function(node,addFlag) {
	var treeObj = this.getZTreeObj();
	treeObj.selectNode(node,addFlag);
	// 触发选中事件
	this.onCurrentNodeSelected && this.onCurrentNodeSelected(node);
};
/**
 * 选中根节点的第一个节点
 */
Tree.prototype.selectFirstRootNode = function(){
	var treeObj = this.getZTreeObj();
	// Logger.debug("common.js => Tree.selectFirstRootNode treeObj => " + JSON.stringify(treeObj));
	var nodes = treeObj.getNodes();
	if (nodes.length>0) {
		treeObj.selectNode(nodes[0]);
		this.onCurrentNodeSelected && this.onCurrentNodeSelected(nodes[0]);
	}
};
/**
 * 根据关键词过滤节点
 * @param key 关键词
 */
Tree.prototype.search = function(key) {
	var $dom = $("#" + this.id);
	if ($.trim(key)) {
		$dom.find("[treenode]").hide();
		$dom.find("[title*='" + key + "']").parents("[treenode]").show();
	} else {
		$dom.find("[treenode]").show();
	}
};
/**
 * 获取记录者
 */
Tree.prototype.getRecorder = function() {
	return this.recorder;
};
/**
 * 记录器
 */
function Recorder() {
	this.updateRecords = new GenericSet();
	this.newRecords = new GenericSet();
	this.deleteRecords = new GenericSet();
}
Recorder.prototype.getUpdateRecords = function() {
	return this.updateRecords;
};
Recorder.prototype.getNewRecords = function() {
	return this.newRecords;
};
Recorder.prototype.getDeleteRecords = function() {
	return this.deleteRecords;
};
Recorder.prototype.clearAll = function() {
	this.updateRecords.arr = [];
	this.newRecords.arr = [];
	this.deleteRecords.arr = [];
};
Recorder.prototype.hasOperate = function() {
	return this.updateRecords.size() + this.newRecords.size() + this.deleteRecords.size() > 0;
};

/**
 * 打包提交到后台
 * @param structure:数组类型，需要打包的数据的结构
 * @author lj
 */
Recorder.prototype.pack = function(structure) {
	var that = this;
	var cleanup = function(arr,structure) {
	    if (!ArrayUtil.hasData(arr)) {
	        return [];
	    }
	    if (!structure) {
	    	return arr;
	    }
	    var mArr = [];
	    $.each(arr, function(index, item){
	        var mObj = {};
	        $.each(structure, function(sIndex, sItem){
	            mObj[sItem] = item[sItem];
	        });
	        mArr.push(mObj);
	    });
	    return mArr;
	};
	return {
		'newRecords': (function(){
			return cleanup(that.newRecords.arr,structure);
		})(), 
		'updateRecords': (function(){
			return cleanup(that.updateRecords.arr,structure);
		})(),
		'deleteRecords':(function(){
			return cleanup(that.deleteRecords.arr,structure);
		})()
	};
};
/**
 * 数据集
 * @param id dataset id
 * @param ajax ajax
 * @param automatic 是否主动从ajax获取数据
 * @author lj
 */
function DataSet(id,ajax,automatic){
	this.id = id;
	this.ajax = ajax;
	this.automatic = automatic;
	
	this.size = 0;
	this.rows = [];
	this.cols = [];
	this.records = [];
}
/**
 * 获取ajax
 */
DataSet.prototype.getAjax = function(){
	return this.ajax;
};
/**
 * 为DataSet提供数据
 * @param json
 */
DataSet.prototype.setJsonData = function(data){
	try{
		var json = data.dataset;
		this.size = data.count;
		this.rows = json.rows;
		this.cols = json.cols;
		this.currentRecord = null;
		this.selectedRecords = [];
		this.records = new Array();
		for(var i = 0;i<this.rows.length;i++){
			var row = this.rows[i];
			var record = new Record(this.cols,row['data'],row['id']);
			this.records.push(record);
		}
	}catch(e){
		Logger.error("common.js => error message => " + e.message);
		Logger.error("common.js => DataSet.setJsonData => parameter:data可能不是一个合法的表格数据，不能正确的转换为DataSet " +
				"data=" + JSON.stringify(data));
	}
};
/**
 * 根据id获取Record
 * @param id
 * @returns
 */
DataSet.prototype.getRecordById = function(id){
	for(var i = 0;i<this.records.length;i++) {
		var record = this.records[i];
		if(record.getId() == id){
			return record;
		}
	}
	Logger.warn("不存在id="+id+"的记录");
	return null;
};
/**
 * 设置当前选中的记录
 * @param id
 */
DataSet.prototype._setCurrentRecord = function(id){
	// Logger.info("id = " + id);
	this.currentRecord = this.getRecordById(id);
};
/**
 * 获取当前记录
 * @returns 
 */
DataSet.prototype.getCurrentRecord = function() {
	return this.currentRecord;
};
/**
 * 设置当前选中的记录
 * @param checkedRecordIdArray
 */
DataSet.prototype._setSelectedRecords = function(checkedRecordIdArray){
	this.selectedRecords=[];
	for(var i = 0;i < checkedRecordIdArray.length;i++){
		var id = checkedRecordIdArray[i];
		var record = this.getRecordById(id);
		this.selectedRecords.push(record);
	}
};
/**
 * 获取当前选中的记录
 * @returns {Array}
 */
DataSet.prototype.getSelectedRecords = function(){
	return this.selectedRecords;
};
/**
 * 获取当前选中的记录的id构成的数组
 */
DataSet.prototype.getSelectedRecordIdArr = function(){
	var ids = new Array();
	for(var i=0;i<this.selectedRecords.length;i++){
		ids.push(this.selectedRecords[i].getId());
	}
	return ids;
};
/**
 * 获取总共有多少条数据
 * @returns {Number}
 */
DataSet.prototype.getSize = function(){
	return this.size;
};
DataSet.prototype.refresh = function(){
	this.ajax.send();
};
/**
 * 行数据，以key:value的形式存储
 */
function Record(cols,row,id){
	this.data = {};
	for(var i= 0;i<cols.length;i++) {
		this.data[cols[i]['name']] = row[i];
	}
	this.id = id;
}
/**
 * 获取记录的id，每一行记录都有一个id唯一标识
 * @returns
 */
Record.prototype.getId = function(){
	return this.id;
};
/**
 * 根据记录的key值获取value值
 * @param key
 * @returns
 */
Record.prototype.get = function(key){
	return this.data[key];
};
Record.prototype.toJson = function(){
	return this.data;
};
Record.prototype.set = function(key,value) {
	this.data[key] = value;
};
function ComplexSelect(id,template,options){
	this.id = id;
	this.options = options;
	switch(template){
	case 'country':
		this.initCountry();
		break;
	case 'ajax':
		this.initByAjax();
		break;
	case 'code':
		this.initByCode();
		break;
	}
}
ComplexSelect.prototype.initCountry = function(){
	var countrySelect = document.getElementById(this.id);
	var countryParams = new Array();
	if(countrySelect) {
		$(countrySelect).find("select").each(function(){
			var id = $(this).attr('id');
			countryParams.push(id);
		});
	}
	if(countryParams.length == 3) {
		this._initCountry(countryParams[0],'',countryParams[1],'',countryParams[2],'');
	}
};
ComplexSelect.prototype._initCountry = function(obj_1,val_1,obj_2,val_2,obj_3,val_3){
	var mp=common_country.mp;
	var mc=common_country.mc;
	var mh = common_country.mh;
	//定义默认数据
	var ar = ["请选择省份","请选择城市","请选择区县"];
	//初始化
	$("<option value=''>"+ar[0]+"</option>").appendTo($("#"+obj_1));
	$("<option value=''>"+ar[1]+"</option>").appendTo($("#"+obj_2));
	$("<option value=''>"+ar[2]+"</option>").appendTo($("#"+obj_3));
	
	var pindex=0;
	var cindex=0;
	//初始化obj_1
	for (var i=0;i<mp.length;i++){
		if (mp[i]==val_1){
			pindex = i;
			$("<option selected>"+mp[i]+"</option>").appendTo($("#"+obj_1));
		}else{
			$("<option>"+mp[i]+"</option>").appendTo($("#"+obj_1));
		}
	}

	if (pindex!=0){
		for (var n=1;n<mc[pindex].length+1;n++){
			if (mc[pindex][n-1]==val_2){
				cindex = n;
				$("<option selected>"+mc[pindex][n-1]+"</option>").appendTo($("#"+obj_2));
			}else{						
				$("<option>"+mc[pindex][n-1]+"</option>").appendTo($("#"+obj_2));
			}			
		}		
	}

	if (cindex!=0){
		for (var m=0;m<mh[pindex][cindex-1].length;m++){
			if (mh[pindex][cindex-1][m]==val_3){
				$("<option selected>"+mh[pindex][cindex-1][m]+"</option>").appendTo($("#"+obj_3));
			}else{						
				$("<option>"+mh[pindex][cindex-1][m]+"</option>").appendTo($("#"+obj_3));
			}	
		}
	}
		
	//响应obj_1的change事件	
	$("#"+obj_1).change(function(){
		//获取索引
		pindex = $("#"+obj_1).get(0).selectedIndex;
		//清空c和h
		$("#"+obj_2).empty();
		//重新给c填充内容
		$("<option>"+ar[1]+"</option>").appendTo($("#"+obj_2));
			if (pindex!=0){
				for (var k=0;k<mc[pindex-1].length;k++){
					$("<option>"+mc[pindex-1][k]+"</option>").appendTo($("#"+obj_2));
				}
			}	
		//清空h
		$("#"+obj_3).empty();
		$("<option>"+ar[2]+"</option>").appendTo($("#"+obj_3));
	});
	
	//响应obj_2的change事件	
	$("#"+obj_2).change(function(){
		cindex = $("#"+obj_2).get(0).selectedIndex;
		//清空h
		$("#"+obj_3).empty();
		//重新给h填充内容
		$("<option>"+ar[2]+"</option>").appendTo($("#"+obj_3));
		if (cindex!=0){
			for (var j=0;j<mh[pindex-1][cindex-1].length;j++){
				$("<option>"+mh[pindex-1][cindex-1][j]+"</option>").appendTo($("#"+obj_3));
			}
		}
	});
};
ComplexSelect.prototype.initByAjax = function(){
	var ajax = this.options.ajax;
	if(ajax == undefined)
		return;
	
	var div = document.getElementById(this.id);
//	var $select = $(div).find("select");
	var selectName = this.options['selectName'];
	var $select = $("<select/>");
	var ajaxDataId = this.options['ajaxDataId'];
	var ajaxDataText = this.options['ajaxDataText'];
	var eventS = this.options['event'];
	var showSelectAll = this.options['showSelectAll'];
	var showSelectValue = this.options['showSelectValue'];
	var showSelectName = this.options['showSelectName'];
	var className = this.options['className'];
	ajax.bindSuccessEvent(function(data,status,xhr){
		if(showSelectAll){
			$select.append($("<option></option>").attr({
				"value":showSelectValue,
				"id":showSelectValue
				}).text(showSelectName));
		}
		$.each(data.info,function(){
			$select.append($("<option></option").attr({
				'id':this[ajaxDataId],
				'value':this[ajaxDataId]
				}).text(this[ajaxDataText]));
		});
		$select.attr('name',selectName).addClass(className);
		$(div).empty();
		$(div).append($select);
		eventS && eventS(data,status,xhr);
	});
	ajax.send();
};
// 加载码表
ComplexSelect.prototype.initByCode = function(){
	var _this = this;
	var options = this.options;
	var opt = {
		'readonly': false,
		'className': ''
	};
	opt = $.extend(opt, options);
	var codeType = opt.codeType;
	var async = opt.async;
	var ajax = new CommonAjax(ctx + "/system/code/findCodeByType", null, {
		'codeType':codeType,
	});
	ajax.async = async;
	var $select = $("<select/>");
	$select.on('change',function(e){
		opt.onChange && opt.onChange(e);
	});
	$select.on('blur', function(e) {
		opt.onBlur && opt.onBlur(e);
	});
	var defaultValue = null;
	if(defaultValue != ''){
		defaultValue = _this.options.defaultValue;
	}
	$select.attr({
		"id":_this.id,
		'name':_this.options.name
	});
	$select.addClass(opt['className']);
	$("div#"+_this.id + ":not([data-tag='done'])").after($select);
	$("div#"+_this.id + ":not([data-tag='done'])").attr("data-tag","done");
	if (opt.readonly == "true") {
		Logger.warn("readonly is true");
		$select.attr({
			'readonly': 'readonly',
			'disabled': 'disabled'
		});
	}
	if(_this.options.showSelectAll){
		var $all = $("<option/>");
		$all.attr({
			"value":_this.options.showSelectValue,
		});
		$all.text(_this.options.showSelectName);
		$select.append($all);
	}
	var buildSelect = function(data){
		if(!data){
			Logger.error("sys code is null, the code type = " + codeType);
			return;
		}
		Logger.warn("opt.readonly = " +  opt.readonly);
		
		$.each(data,function(index,item){
			var $option = $("<option/>");
			$option.attr({
				"value":item['codeInfoValue'],
				"data-name":item['codeInfoName']
			});
			$option.text(item['codeInfoName']);
			if(defaultValue != null && defaultValue != '' && defaultValue == item['codeInfoValue']){
				$option.prop("selected","selected")
			}
			$select.append($option);
		});
	};
	ajax.bindSuccessEvent(function(data,status,xhr){
		buildSelect(data.info);
		$("div#"+_this.id).remove();
		opt.event && opt.event(data,status,xhr);
	});
	//ajax.send();
};
/**
 * 处理tag标签的业务逻辑
 */
function TagSupport(opt){
	this.opt = opt;
}
TagSupport.prototype.kindeditor = function(){
	var _opt = this.opt;
	var $inp = $("<input type='hidden' />");
	$inp.attr({
		"name":_opt.inpName,
		"id":_opt.inpId
	});
	var $textarea = $("<textarea class='form-control kindeditorSimple'/>");
	$textarea.attr({
		"name":_opt.name,
		"id":_opt.id
	});
	$(".richText").append($textarea);
	$(".richText").append($inp);
	window[_opt.id] = KindEditor.create('#'+_opt.id, {
  	    basePath: _opt.basePath,
  	    bodyClass : _opt.bodyClass,
  	    items : ['fontname', 'fontsize', '|', 'forecolor', 'hilitecolor', 'bold', 'italic', 'underline',
  	             'removeformat', '|', 'justifyleft', 'justifycenter', 'justifyright', 'insertorderedlist',
  	             'insertunorderedlist', '|', 'emoticons', 'image', 'link'],
  	     allowFileManager : _opt.allowFileManager,
  	     height:_opt.height,
  	     width: _opt.width,
  	     allowImageRemote: _opt.allowImageRemote
  	});
	
}



/**
 * 根据员工编号获取员工姓名
 * @Param spanId 用于显示的span  id
 * @param	staffId：员工id
 * @Param type 结果类型，可选值:1、'name',结果为 name,默认; 2、nameId 结果为 name(id)
 */
function TansStaffNameById(spanId,staffId,type,className){
	console.log(spanId);
	this.staffId = staffId;
	this.type = type;
	var ajax = new CommonAjax(ctx + "/system/staff/findNameById", null, {
		'staffId':staffId,
	});
	ajax.bindSuccessEvent(function(data,status,xhr){
		var name = data.info;
		switch(type){
		case 'name':
			$('span#'+spanId).html(name);
			break;
		case 'nameId':
			$('span#'+spanId).html(name+'('+staffId+')');
			break;
		}
		$('span#'+spanId).addClass(className);
	});
	ajax.send();
}
// 扩展字符串功能
if(!String.prototype.endsWith) {
    String.prototype.endsWith = function(searchString, position) {
        var subjectString = this.toString();
        if(position === undefined || position > subjectString.length) {
            position = subjectString.length;
        }
        position -= searchString.length;
        var lastIndex = subjectString.indexOf(searchString, position);
        return lastIndex !== -1 && lastIndex === position;
    };
};

if(!String.prototype.startsWith) {
    String.prototype.startsWith = function(searchString, position) {
        position = position || 0;
        return this.lastIndexOf(searchString, position) === position;
    };
};

if(!String.prototype.includes) {
    String.prototype.includes = function() {
        return String.prototype.indexOf.apply(this, arguments) !== -1;
    };
};

/**
 * 列定义
 * name 后台vo对应字段名
 * display 页面显示名称
 * width 宽度
 * ignore 是否显示
 * flex 
 * type 列数据类型
 * sort 是否启用排序
 * cssClass 列头样式类
 * dataCssClass 列数据样式类
 */
function Col(name,display,width,ignore,flex,type,sort,cssClass,dataCssClass){
	this.name = name;
	this.text = display;
	this.width = width;
	this.ignore = ignore;
	this.flex = flex;
	this.type = type;
	this.sort = sort;
	this.cssClass = cssClass;
	this.dataCssClass = dataCssClass;
};
Col.prototype.getName = function(){
	return this.name;
};
//列定义数组
function ColsDef(id){
	this.id = id;
	this.arr = [];			//列定义具体信息
	this.colSort = [];		//列的排序规则，列name
};

ColsDef.prototype.addCol = function(col){
	this.arr.push(col);
	this.colSort.push(col.getName());
};
ColsDef.prototype.getCols = function(){
	return this.arr;
};
ColsDef.prototype.getSort = function(){
	return this.colSort;
};
//单行定义
function Row(index){
	this.data = [];		//具体数据
	this.id = index;
}
Row.prototype.setData = function(data){
	for(var i in data){
		this.data.push(data[i]);
	}
};
//行定义数组
function Rows(){
	this.cols = [];
	this.rows = [];
};
Rows.prototype.set = function(cols,rows){
	this.cols=cols;
	//rows为空
	if(!!rows && rows.length == 0){
		Logger.info("rows is empty!");
	}else{
		for(var i in rows){
			var row = new Row(i);
			var datas = [];
			//排序
			for(var col in cols){
				var name = cols[col].name;
				var data = rows[i][name];
				datas.push(data);
			}
			row.setData(datas);
			this.rows.push(row);
		}
	}
};
//数据表格信息定义
function TableInfo(isSuccess,total){
	this.isSuccess = isSuccess;	//是否成功
	this.count = total;			//数据总数
	this.dataset = new Rows();	//当前所有数据行的具体信息
};
TableInfo.prototype.setColsRows = function(cols,rows){
	this.dataset.set(cols,rows);
};

/**
 * 普通类型的集合，针对字符串，整型等基础数据类型
 */
function GenericSet(arr){
	this.arr=arr;
	if(this.arr==undefined)
		this.arr=new Array();
}
/**
 * 往GenericSet中添加数据
 * 
 */
GenericSet.prototype.put=function(data){
	var _this=this;
	$.each(this.arr,function(index,item){
		if(data==item){
			_this.arr.splice(index,1); // 若存在，删除掉
		}
	});
	this.arr.push(data);
};
GenericSet.prototype.putByKey=function(data, key){
	var _this=this;
	$.each(this.arr,function(index,item){
		if (item == undefined) {
			return ;
		} 
		if (data[key] == item[key]) {
			_this.arr.splice(index,1); // 若存在，删除掉
		}
	});
	this.arr.push(data);
};
GenericSet.prototype.remove=function(data,correct){
	var _this = this;
	$.each(this.arr,function(index,item){
		if(data==item){
			_this.arr.splice(index,1);
		}
	});
	if(correct){
		$.each(this.arr,function(index,item){
			if(item>data){
				_this.arr[index]=item-1;
			}
		});
	}
};
GenericSet.prototype.removeByKey = function(data, key) {
	var _this = this;
	$.each(this.arr,function(index,item){
		if (item == undefined) {
			return ;
		} 
		if (item[key] == data[key]){
			_this.arr.splice(index,1);
		}
	});
};
GenericSet.prototype.hasItem = function(data) {
	var has = false;
	$.each(this.arr,function(index,item){
		if (item == undefined) {
			return ;
		} 
		if (item == data){
			has = true;
		}
	});
	return has;
	
};
GenericSet.prototype.hasItemOfKey = function(data, key) {
	var has = false;
	$.each(this.arr,function(index,item){
		if (item == undefined) {
			return ;
		} 
		if (item[key] == data[key]){
			has = true;
		}
	});
	return has;
};
GenericSet.prototype.size=function(){
	return this.arr.length;
};
GenericSet.prototype.hasData=function(){
	return this.arr.length > 0;
};
GenericSet.prototype.getByIndex=function(index){
	return this.arr[index];
};
GenericSet.prototype.latest=function(){
	if(this.arr.length<=0)
		throw new Error("GenericSet instance is empty");
	return this.arr[this.arr.length-1];
};
// 获取除开arr之外的所有
GenericSet.prototype.except = function(arr) {
	var resultArr = new Array();
	$.extend(resultArr, this.arr);
	$.each(arr,function(index,item){
		var mIndex = $.inArray(item,resultArr);
		if (mIndex >= 0) {
			resultArr.splice(mIndex, 1);
		}
	});
	return resultArr;
};
// 判断数据是否存在于GenericSet.arr对象中
GenericSet.prototype.exist=function(data){
	var exist = false;
	$.each(this.arr,function(index,item){
		if(data==item){
			exist=true;
		}
	});
	return exist;
};
GenericSet.prototype.existByKey=function(data,key){
	var exist = false;
	$.each(this.arr,function(index,item){
		if (item == undefined) {
			return ;
		} 
		if(data[key]==item[key]){
			exist=true;
		}
	});
	return exist;
};
GenericSet.prototype.clear=function(){
	this.arr=new Array();
};
/**
 * 判断arr中的数据是否都在GenericSet.arr中
 */
GenericSet.prototype.containsAll=function(arr){
	for(var i = 0 ; i < arr.length; i++ ) {
		if (!this.exist(arr[i])) {
			return false;
		}
	}
	return true;
};
GenericSet.prototype.containsAllOfKey=function(arr, key){
	for(var i = 0 ; i < arr.length; i++ ) {
		if (!this.existByKey(arr[i][key])) {
			return false;
		}
	}
	return true;
};
/**
 * 合并GenericSet
 * @param gset
 */
GenericSet.prototype.merge = function(gset) {
	if (gset.arr.length <= 0) {
		return this;
	}
	for (var i = 0; i < gset.arr.length; i++ ){
		var item = gset.arr[i];
		this.put(item);
	}
	return this;
};
GenericSet.prototype.mergeOfKey = function(gset, key) {
	if (gset.arr.length <= 0) {
		return this;
	}
	for (var i = 0; i < gset.arr.length; i++ ){
		var item = gset.arr[i];
		this.putByKey(item);
	}
	return this;
};

(function($){
	$.extend({
		/**
		 * jquery plugins
		 * @功能：将数组形式的对象转为树形结构的对象
		 * @作者：lj
		 * @日期：2017-04-03
		 */
		// 对于tree而言，options中必须定义的项：
		//{
//			"data":[]
//			"rootPidValue":null,
//			"children":"children",
//			"contentDefine":{
//				"id":"id",
//				"pid":"pid"
//			}
		//}
		toTree:function(options){
			if(!options){
				options = {};
			}
			var data = options.data;
			var contentDefine = options.contentDefine;
			
			var getChild = function(mData,pid){
				var menus = [];
				$.each(mData,function(index,item){
					if(item[contentDefine.pid] == pid){
						var obj = new Object();
						$.extend(obj,item);
						
						$.each(contentDefine,function(key,val){
							obj[key] = item[val];
						});
						
						var children = getChild(mData,item[contentDefine.id]);
						obj[options.children] = children;
						menus.push(obj);
					}
				});
				return menus;
			};
			return getChild(data,options.rootPidValue);
		},
		/**
		 * jquery plugins
		 * @功能：漂浮消息提示
		 * @作者：lj
		 * @日期：2017-04-20
		 */
		messager:{
			warn:function(msg,options){$.messager._show(msg,'warning',options);},
			info:function(msg,options){$.messager._show(msg,'info',options);},
			error:function(msg,options){$.messager._show(msg,'danger',options);},
			success:function(msg,options){$.messager._show(msg,'success',options);},
			important:function(msg,options){$.messager._show(msg,'important',options);},
			_show:function(msg,type,options){
				var mOptions = {
					'type': type,
					'time': 2000,
				};
				$.extend(mOptions,options);
				new $.zui.Messager(msg, mOptions).show();
			}
		},
		/**
		 * jquery plugins
		 * @功能：将对象数组转为单一的某个属性值组成的数组
		 * @示例：输入 
		 * <p>var arr = [{'id':1,'name':'tom'},{'id':2,'name':'susan'}];</p>
		 * <p>var property = 'id';</p>
		 * <p>var result = $.toPropertyArray(arr,property)</p>
		 * <p>// result=[1,2]</p>
		 * @作者：lj
		 * @日期：2017-04-21 
		 */
		toPropertyValueArray:function(array,property){
			var arr = [];
			if(!array || array.length<=0 || !array instanceof Array){
				return arr;
			}
			$.each(array,function(index,item){
				arr.push(item[property]);
			});
			return arr;
		},
		/**
		 * jquery plugins
		 * @功能：根据option的value获取&lt;select&gt;标签下的option的text值
		 * @参数：
		 * <p>jqid:$("#xxx")：<strong>select标签的jquery id</strong></p>
		 * <p>value:"1001"：<strong>option的value值</strong></p>
		 * @示例
		 */
		getDropOptionText:function(jqid, value) {
			return $(jqid).find("option[value='" + value + "']").text();
		},
		getIframeId:function() {
			var iframeId = null;
			var mWindow = window;
			$(top.document.body).find("iframe").each(function(){
				var fid = $(this).data("id");
				if (this.contentWindow == mWindow) {
					iframeId = fid;
				};
			});
			return iframeId;
		},
		/**
		 * session超时统一处理
		 */
		sessionTimeoutHandle:function(xhr, textStatus) {
			var handle = function() {
				if (!xhr.hasDone) {
					MsgBox.stopLoading();
					// 如果超时就处理 ，指定要跳转的页面
					MsgBox.error("会话超时，立即重新登录", null, function() {
						top.window.location.href = ctx;
					});
					xhr.hasDone = true;
				}
			};
			
			if (xhr.getAllResponseHeaders().contains("sessionstatus")) {
				handle();
				return ;
			}
			
			//通过XMLHttpRequest取得响应头，sessionstatus，  
	        var sessionstatus=xhr.getResponseHeader("sessionstatus");   
	        Logger.warn("sessionStatus = " + sessionstatus);
	        if(sessionstatus=="timeout"){
	        	handle();
	        	return ;
	        }
		},
		/**
		 * @功能：自定义ajax请求，系统中所有的ajax请求均应该用此ajax请求
		 * @作者：刘杰
		 * @日期：2017-05-26
		 */
		mAjax:function(options) {
			var opt = {
				'timeout': 30000, // 默认超时时间设置为30秒
			};
			$.extend(opt, options);
			opt.mcomplete = opt.complete;
			opt.msuccess = opt.success;
			opt.merror = opt.error;
			delete opt.complete;
			delete opt.success;
			delete opt.error;
			var setting = {
				'complete':function(xhr, status) {
					MsgBox.stopLoading();
					$.sessionTimeoutHandle(xhr, status);
					ObjectUtil.isFunction(opt.mcomplete) && opt.mcomplete(data, xhr, status);
				},
				'success':function(data, status, xhr) {
					MsgBox.stopLoading();
					$.sessionTimeoutHandle(xhr, status);
					ObjectUtil.isFunction(opt.msuccess) && opt.msuccess(data, xhr, status);
				},
				'error':function(xhr,textStatus,errorThrown) {
					MsgBox.stopLoading();
					$.sessionTimeoutHandle(xhr, textStatus);
					ObjectUtil.isFunction(opt.merror) && opt.merror(xhr,textStatus,errorThrown);
				}
			};
			$.extend(setting, opt);
			if (!opt.silent) {
				MsgBox.startLoading();
			}
			$.ajax(setting);
		},
		/**
		 * jquery plugins
		 * $('#xx').mBuildSelect({})
		 * @属性：<p>id,name,className,
		 * showSelectAll,showSelectName,showSelectValue,readonly,defaultValue,
		 * data[{value,text}],defaultIndex</p>
		 * @功能：下拉菜单
		 * @作者：lj
		 * @日期：2017-05-31
		 * @调用：dropList.tag
		 */
		_buildSelect:function(options) {
			var opt = {
				'showSelectName':'全部',
				'showSelectValue':''
			};
			opt = $.extend(opt, options);
			var $select = $("<select/>");
			$select.attr({
				'id':opt.id,
				'name':opt.name
			});
			if (opt.readonly) {
				$select.attr({
					'disabled':'disabled',
					'readonly':'readonly'
				});
			}
			opt.className && $select.attr('class',opt.className);
			if (opt.showSelectAll) {
				var $option = $('<option/>');
				$option.attr({
					'value':opt.showSelectValue
				});
				if (!opt.defaultValue) {
					$option.attr('selected', 'selected');
				}
				$option.text(opt.showSelectName);
				$select.append($option);
			}
			if ( ArrayUtil.hasData(opt.data)) {
				$.each(opt.data, function(index, item) {
					var $option = $('<option/>');
					$option.attr({
						'value':item['value'],
						'data-index':index
					});
					$option.text(item['text']);
					$select.append($option);
				});
			}
			if (ObjectUtil.isInteger(opt.defaultIndex)) {
				var defaultIndex = parseInt(opt.defaultIndex);
				if (defaultIndex < 0) defaultIndex = 0;
				if (ArrayUtil.hasData(opt.data) && defaultIndex >= opt.data.length) defaultIndex = opt.data.length-1;
				$select.find('option[data-index="' + defaultIndex + '"]').attr('selected','selected');
			}
			if (opt.defaultValue) {
				$select.find('option[value="' + opt.defaultValue + '"]').attr('selected','selected');
			}
			return $select;
		},
		/**
		 * @功能 构造一个带小图标的超链接
		 * @参数 options{type,className,click->function,title}
		 * @日期 20170615
		 */
		buildIconLink:function(options) {
			var opt = {
				'ICON_TYPE':{
					'edit':{
						'className': 'icon icon-edit'
					},
					'delete':{
						'className': 'icon icon-trash'
					},
					'view':{
						'className': 'icon icon-eye-open'
					},
					'reply':{
						'className': 'icon icon-reply'
					},
					'point':{
						'className':'icon icon-hand-right'
					},
					'forbid':{
						'className':'icon icon-minus-sign m-color-red'
					}
				}
			};
			$.extend(opt, options);
			var $link = $("<a href='javascript:void(0);'></a>");
			var $icon = $("<i></i>");
			opt.type && $icon.addClass(opt.ICON_TYPE[opt.type].className);
			opt.className && $icon.addClass(opt.className);
			opt.click && $link.on('click',function(e) {
				e.stopPropagation();
				e.preventDefault();
				opt.click(e);
			});
			$link.append($icon);
			$link.attr({
				'title':(opt.title || ''),
				'class':'m-icon-link'
			});
			return $link;
		},
		/**
		 * jquery plugins
		 * @功能：下载文件
		 * @作者：lj
		 * @参数：{url,type,data}
		 * @日期：2017-8-15
		 */
		download:function(options) {
			var opt = {
				'type':'get'
			};
			$.extend(opt, options);
			var $frm = $("<form></form");
			$frm.attr({
				'action': opt.url,
				'method': opt.type
			});
			if (opt.data != null) {
				$.each(opt.data, function(key, value) {
					var $input = $("<input hidden='hidden'>");
					$input.attr({
						'name': key,
						'value': value
					});
					$frm.append($input);
				});
			}
			$frm.appendTo("body").submit().remove();
		},

	});
	$.fn.extend({
		/**
		 * jquery plugins
		 * @功能：根据指定url加载页面代码到指定位置
		 * @作者：lj
		 * @日期：20170406
		 */
		//options= {
		//	"url":"",
		//  "data":"",
		//  "type":"",
		//  "preLoadPage":function(xhr){},
		//  "successLoaded":function(data,status,xhr){},
		//  "errorLoadPage":function(xhr,textStatus,errorThrown){},
		//  "completeLoadPage":function(){},
		//  "handleHtml":function(html){ return html;},
		//  'custDeal': function(id, name, url){}
		//}
		// $(".xxx").loadPage(options);
		loadPage:function(options){
			options = options || {};
			// 校验url
			if(options.url == ctx){
				return ;
			}
			var params = options.data || "";
			var type = options.type || "get";
			// 支持跨域请求
			if(options.url.startsWith('http://')){
				options.dataType='jsonp';
			} else {
				options.dataType = 'text';
			}
			if(options.url=="/" || $.trim(options.url)==""){
				Logger.info("不能打开url路径为'/' 或 ''的页面");
				// MsgBox.error("无法打开此页面");
				return ;
			}
			// 输出HTML文档的方法
			var _this = this;
			var outputHtml = function(data){
				_this.addClass("m-hide");
				var $article = $();
				$(data).each(function(){
					var tagName = $(this).prop("tagName");
					if(tagName) {
						if($(this).attr("data-appendToBody")!="false" && $(this).attr("data-appendToBody")){
							if($(this).attr("role") == "dialog" && $(this).hasClass('modal fade')){
								var _thisId = $(this).attr("id");
								if($(top.document.body).find("#"+_thisId).length == 0){
									$(top.document.body).append($(this));
								}
							}else{
								$(top.document.body).append($(this));
							}
						}else{
							$article = $article.add($(this));
						}
					}
				});
				_this.empty().append($article);
				_this.removeClass("m-hide");
			};
			// 判断是否缓存有页面数据，尝试从缓存中取
			options.data || (options.data = {}); 
			if(options.data[options.url] != null){
				var data = options.data[options.url];
				outputHtml(data);
				return ;
			}
			!options.silent && MsgBox.startLoading();
			$.ajax({
				async:options.async == undefined ? true : options.async,
				url:options.url,
				type:type,
				"data":params,
				'dataType':options.dataType || "text",
				'contentType' : options.contentType || 'application/x-www-form-urlencoded',
				'jsonp':'callback',
				'jsonpCallback':"success_jsonpCallback",
				'success':function(data,status,xhr){
					$.sessionTimeoutHandle(xhr, status);
					try{
						var html = options.handleHtml && options.handleHtml(data);
						html ? outputHtml(html) : outputHtml(data);
					}catch(e){
						window["console"] && console.error(e);
						Logger.error(e);
					}
					!options.silent && MsgBox.stopLoading();
					options.successLoaded && options.successLoaded(data,status,xhr);
				},
				'complete':function(XMLHttpRequest, textStatus){
					!options.silent && MsgBox.stopLoading();
					options.completeLoadPage && options.completeLoadPage();
					$.sessionTimeoutHandle(XMLHttpRequest, textStatus);
				},
				'beforeSend':function(xhr){
					options.preLoadPage && options.preLoadPage(xhr);
				},
				'error': function(xhr,textStatus,errorThrown) {
					options.errorLoadPage && options.errorLoadPage(xhr,textStatus,errorThrown);
					Logger.error('you encountered an error while sending ajax');
					Logger.error(errorThrown);
					$.messager.error("错误：加载页面失败",{
						'placement':"center"
					});
					!options.silent && MsgBox.stopLoading();
				}
			});
		},
		/**
		 * jquery plugins
		 * @功能：tab set
		 * @作者：lj
		 * @日期：20170406
		 */
		//options = {
		//  "$parentBody":$("#serviceInQuiryDiv"),
		//	"preClose":function(){ // 关闭页面之前执行的方法
		//	},
		//	"preOpen":function(){ // 打开页面之前执行的方法
		//	},
		//	"preActiveTab":function(){ // 激活某个标签页之前执行的方法
		//	},
		//}
		tabset:function(options){
			Logger.warn("this.length = " + this.length);
			
			// 初始化options.$body
			options.$body = $(this.data("tab-toggle"));
			// 获取激活历史
			var getActiveHistory = function() {
				var $tabset = options.$body.find(".m-tabset");
				var arr = $tabset.data("active-history");
				var activeHistory = new GenericSet(arr);
				return activeHistory;
			};
			// 保存激活历史
			var saveActiveHistory = function(activeHistory) {
				var $tabset = options.$body.find(".m-tabset");
				$tabset.attr("data-active-history", JSON.stringify(activeHistory));
			};
			// console.log("enter");
			// on tab close event
			// steps of close tab：
			// 1. set $tabBody attribute: data-active=false
			// 2. set $tab attribute: data-active=false, data-join=false
			// 3. 判断是否所有$tab的attribute[data-join]都为false，若是，设置$tabContainer的data-active=false,
			//       同时设置$parentBody.show()
			var _this = this;
			var closeTab = function(e, $tab, id){ // e:click event, id:$tab的id
				
				var activeHistory = getActiveHistory();
				activeHistory.remove(id);
				saveActiveHistory(activeHistory.arr);
				// 1. 关闭当前要关闭的
				$tab.remove();
				var $tabBody = options.$body.find(".m-bodyset>.m-tab-body[data-id='"+ id +"']");
				$tabBody.remove();
				// 2. 激活最近一次打开的
				try {
					activeTab(activeHistory.latest());
				} catch(e) {}
				// 3. 如果tabset中没有激活的，则呈现parentBody，options.$body关闭
				if(_this.data("tab-single-body")) $tabBody.remove(); // when single body is true, remove $tabBody
				if( options.$body.find(".m-tabset>ul>li.m-tab[data-join='true']").length ==0 ){
					options.$body.attr("data-active",false);
					options.$parentBody.show();
				}
				
				e.stopPropagation();
				e.preventDefault();
			};
			// build tab set
			var buildTabSet = function(){
				if(options.$body.find(".m-tabset").length <= 0){
					var $tabset = $("<div class='m-tabset'></div>");
					var $ul = $("<ul/>");
					$tabset.append($ul);
					options.$body.append($tabset);
				}
			};
			var buildBodySet = function(){
				if(options.$body.find(".m-bodyset").length == 0){
					var $bodyset = $("<div class='m-bodyset'></div>");
					options.$body.append($bodyset);		
				}
			};

			var loadTabSetData = function(){
				var data = new Array();
				$.each(_this,function(index, btn){
					var url = $(this).data('tab-url');
					var title = $(this).data('tab-title');
					var id = $(this).data('tab-id');
					data.push({
						"id":id,
						"url":url,
						"title":title,
						"active":false,
						"join":false
					});
				});
				return data;
			};
			
			var joinTab = function(id, title, url){
				// 1. 隐藏父布局
				options.$parentBody.hide();
				// 2. 显示tabContainer
				options.$body.attr({
					"data-active":true
				});
				var $tabset = options.$body.find(".m-tabset");
				var $tab = $tabset.find(".m-tab[data-id='"+ id +"']");
				if ($tab.length == 0) {
					var $li = $("<li/>");
					$li.addClass("m-tab");
					$li.attr({
						"data-url":url,
						"data-title":title,
						"data-id":id,
						"data-join":true,
						"data-active":false
					});
					var $a = $("<a/>");
					$a.attr({
						"data-title":title,
						"data-url":url,
						"href":url,
						"title":"点击刷新"
					});
					var $i = $("<i class='fa fa-fw fa-times-circle'/>");
					$a.append($i);
					$i.after(title);
					// 绑定关闭事件
					$i.off('click').on('click',function(e){
						closeTab(e, $li, id);
					});
					// 绑定$a点击事件
					$a.off('click').on('click',function(e){
						e.stopPropagation();
						e.preventDefault();
						// 0. 变更和保存激活历史
						var activeHistory = getActiveHistory();
						activeHistory.put(id);
						saveActiveHistory(activeHistory.arr);
						// 刷新页面
						var $tabBody = options.$body.find(".m-bodyset>.m-tab-body[data-id='"+ id +"']");
						$tabBody.attr("data-active")=="true" && $tabBody.empty().loadPage({
							"url":url
						});
						options.$body.find(".m-bodyset>.m-tab-body").attr("data-active", false);
						$tabBody.attr("data-active", true);
						$tabset.find(".m-tab").attr("data-active", false);
						$(this).closest("li").attr("data-active", true);
					});
					$li.append($a);
					$tabset.find("ul").append($li);
				} else {
					$tab.attr("data-join", true);
				}
			};
			var activeTab = function(id,reload){
				// 0. 变更和保存激活历史
				var activeHistory = getActiveHistory();
				activeHistory.put(id);
				saveActiveHistory(activeHistory.arr);
				
				// 1.1 将所有激活的m-tab变为不激活，激活当前需要激活的tab
				options.$body.find(".m-tab[data-active='true']").attr("data-active",false);
				var $tab = options.$body.find(".m-tab[data-id='"+ id +"']");
				$tab.attr("data-active",true);
				// 1.2 将所有激活的m-tab-body变为不激活，激活当前需要激活的tab-body
				var $bodyset = options.$body.find(".m-bodyset");
				// 查找是否存在此body，存在则显示，不存在则输出
				$bodyset.find(".m-tab-body[data-active='true']").attr("data-active",false);
				var $tabBody = $bodyset.find(".m-tab-body[data-id='"+ id +"']");
				// if not exist body, then output body and set attribute: data-active=true
				if($tabBody.length == 0) {
					$tabBody = $("<div/>");
					$tabBody.attr({
						"data-id":id,
						"class":"m-tab-body",
					});
					$bodyset.append($tabBody);
				} else {
					$tabBody.attr("data-active", true);
				}
				if(reload){
					// reload page
					$tabBody.loadPage({
						"url":$tab.data("url"),
						"successLoaded":function(data,status,xhr){
							$tabBody.attr("data-active",true);
						},
						"errorLoadPage":function(xhr,textStatus,errorThrown){
							$tabBody.attr("data-active",true);
						},
						"completeLoadPage":function(){
							$tabBody.attr("data-active",true);
						}
					});
				}
			};
			// 1. 装载tabset数据
			options.latestData = loadTabSetData();
			// 2. 输出tabset
			buildTabSet();
			// 3. 输出bodyset
			buildBodySet();
			
			$.each(this,function(index, btn){
				$(btn).off('click').on('click',function(e){
					// 根据id激活tab
					var id = $(this).data("tab-id");
					var title = $(this).data('tab-title');
					var url = $(this).data('tab-url');
					if (options.custDeal) {
						options.custDeal(id, title, url);
					} else {
						// join tab
						joinTab(id, title, url);
						// active tab
						activeTab(id, true);
					}
				});
			});
		},
		/**
		 * jquery plugins
		 * @功能：下拉列表
		 * @作者：lj
		 * @日期：20170411
		 */
		// options = {
//	 	"triggerBtn":$("#searchBtn"), // 非必须
//	 	"onRenderItem":function(index,item,$a){ // 非必须
//	 		return $a;
//	 	},
//	 	"contentDefine":{
//	 		"id":"searchId",
//	 		"text":"showTitle"
//	 	},
//	 	"ajaxSetting":function(){
//	 		return {
//	 			"type":"GET",
//	 			"url":"sms/platform/search/"+escape($("input[name='searchKey']").val()),
//	 			"success":function(data,status,xhr){
//	 			}
//	 		};
//	 	},
//	 	"cssClass":"t-search-droplist",
	//  "silent":false, // 非必须
	//  "autocomplete":false, // 非必须
	//  "keySupport":false, // 非必须
	//  "timeout":150, // 非必须，默认150ms
	//  "onEnterKeyDown":function(val){}, // 敲Entere键触发的事件
	//  "onOutputErrorContent":function($container){}  // 请用$container拼接DOM或者返回待拼接的$DOM
	//  "onItemClick": function(e) {} // 点击事件
	// }
		dropList:function(options){
			var DEFAULT_EMPTY_PROMPT = "没有找到查询结果";
			var TIME_OUT = 200;
			
			var $this = this;
			var $mInput = options.input;
			var $mTriggerBtn = options.triggerBtn;
			var onRendItemFunc = options.onRenderItem;
			var ajaxSetting = options.ajaxSetting;
			var contentDefine = options.contentDefine;
			var onItemClick = options.onItemClick;
			var silent = options.silent;
			var cssClass= options.cssClass;
			var emptyPrompt = options.emptyPrompt || DEFAULT_EMPTY_PROMPT;
			var keySupport = options.keySupport || false;
			var timeout = options.timeout || TIME_OUT;
			var onEnterKeyDown = options.onEnterKeyDown;
			var onOutputErrorContent = options.onOutputErrorContent;
			
			// 输出列表内容
			var outputList = function(data){
				// 清空内容
				$this.parent().find(".m-drop-list").remove();
				$this.parent().find(".error-prompt").remove();
				// 发送ajax请求，输出内容
				var $ul = $("<ul/>");
				$ul.on('mouseleave blur',function(){
					removeDropList();
				});
				$ul.addClass("m-drop-list m-ul-pure");
				cssClass && $ul.addClass(cssClass);
				$.each(data,function(index, item){
					var $li = $("<li/>");
					$li.addClass("drop-item");
					$li.attr({
						"data-id":(contentDefine.id ? item[contentDefine.id] : "")
					});
					var $itemDom = $(itemDom);
					$li.append($itemDom);
					// 默认模式
					var $a = $("<a/>");
					$a.attr({
						"href":item.url,
					});
					$a.on('click',function(e){
						onItemClick && onItemClick(e);
						removeDropList();
					});
					contentDefine.text && $a.text(item[contentDefine.text]);
					var itemDom = onRendItemFunc && onRendItemFunc(index,item,$a);
					if(itemDom) $li.append(itemDom);
					else $li.append($a);
					$ul.append($li);
				});
				$this.after($ul);
				$ul.css("display","none");
				$ul.slideDown(200);
				$ul.focus();
			};
			// 移除下拉错误框
			var removeErrorContent = function(){
				$this.parent().find(".error-prompt").slideUp(200);
				setTimeout(function(){
					$this.parent().find(".error-prompt").remove();
				},200);
			};
			// 移除下拉列表
			var removeDropList = function(){
				$this.parent().find(".m-drop-list").slideUp(200);
				setTimeout(function(){
					$this.parent().find(".m-drop-list").remove();
				},200);
			};
			// 移除所有下拉
			var removeDrop = function() {
				removeDropList();
				removeErrorContent();
			};
			// 输出错误内容
			var outputErrorContent = function(errorText){
				$this.parent().find(".m-drop-list").remove();
				$this.parent().find(".error-prompt").remove();
				var $errorContent = $("<p></p>");
				$errorContent.addClass("error-prompt");
				if (onOutputErrorContent) {
					var $dom = onOutputErrorContent($errorContent, errorText);
					$dom && $errorContent.append($dom);
				} else {
					$errorContent.text(errorText);
				}
				$errorContent.on('mouseleave blur',function(e){
					removeErrorContent();
				});
				$this.after($errorContent);
			};
			// 处理回车和搜索按钮点击事件
			var handle = function($dom, val){
				var _ajaxSetting = null;
				if(typeof ajaxSetting=="function"){
					_ajaxSetting = ajaxSetting();
				}
				if(_ajaxSetting && _ajaxSetting.url){
					var mAjaxSetting = {
						success:_ajaxSetting.success,
						error:_ajaxSetting.error,
						complete:_ajaxSetting.complete,
						beforeSend:_ajaxSetting.beforeSend
					};
					_ajaxSetting.success = function(data,status,xhr){
						$.sessionTimeoutHandle(xhr, status);
						
						Logger.info("=>" + JSON.stringify(data));
						if(typeof data =="string"){
							data = JSON.parse(data);
						}
						if(data.success) {
							// data.info 返回List
							// data.info.data => 分页查询数据
							var mData = null;
							if (data.info && data.info instanceof Array && data.info.length > 0) mData = data.info;
							if (data.info.data && data.info.data instanceof Array && data.info.data.length>0) mData = data.info.data;
							if (mData){
								outputList(mData);
							} else {
								outputErrorContent(emptyPrompt);
							}
						}
						mAjaxSetting.success && mAjaxSetting.success(data,status,xhr);
						options.silent || MsgBox.stopLoading();
					};
					_ajaxSetting.error = function(xhr,textStatus,errorThrown){
						outputErrorContent(emptyPrompt);
						Logger.info("=>" + JSON.stringify(textStatus));
						mAjaxSetting.error && mAjaxSetting.error(xhr,textStatus,errorThrown);
						options.silent || MsgBox.stopLoading();
					};
					_ajaxSetting.complete = function(XMLHttpRequest, textStatus){
						/*var data=request.responseJSON;
						if(data.ret!=null&&data.ret==302){//根据服务器端返回的数据判断
							window.location=data.redirectUrl;
						}
*/
						$.sessionTimeoutHandle(XMLHttpRequest, textStatus);
						mAjaxSetting.complete && mAjaxSetting.complete(event,request, settings);
						options.silent || MsgBox.stopLoading();
					};
					_ajaxSetting.beforeSend = function(xhr){
						mAjaxSetting.beforeSend && mAjaxSetting.beforeSend(xhr);
					};
					
					!silent && MsgBox.startLoading();
					
					var lastTime = $this.data("time") || 0;
					var currTime = (new Date()).getTime();
					if (currTime - lastTime < timeout) {
						// 清除上次的定时器
						var timeOutId = $this.data("timeout-id");
						clearTimeout(timeOutId);
					}
					var timeOutId = setTimeout(function(){
						$.ajax(_ajaxSetting);
					}, timeout);
					$this.data("timeout-id", timeOutId);
					$this.data("time", currTime);

				} else {
					if(options.data && options.data instanceof Array && options.data.length>0) outputList(options.data);
					else outputErrorContent(emptyPrompt);
				}
			};
			// 绑定按键事件
			$this.on("keydown",function(e){
				Logger.warn("e.which = - " + e.which);
				var code = e.which;
				if(code == 27){ // Esc
					$this.val("");// 清空内容
					$this.parent().find(".m-clear-btn").remove();
				} else if(code == 13){ // 回车
					var key = "droplist-100001";
					if(!MsgBox.preventViolentClick(key,"",500,false)){
						if (onEnterKeyDown) {
							var mDoneOpt = onEnterKeyDown($(this).val());
							if (mDoneOpt) {
								if (mDoneOpt.doRemove) {
									removeDrop();
								}
							}
						} else {
							Logger.info("执行请求");
							handle($(this),$(this).val());
						}
					};
				} else if (code == 40) { // ↓
					
				} else if (code == 38) { // ↑
					
				}
				e.stopPropagation();
			});
			$this.bind('input propertychange',function(e){
				var len = $this.val().length;
				if(len > 0){
					if( $this.parent().find(".m-clear-btn").length==0){
						var $clearBtn = $("<i class='fa fa-fw fa-times-circle m-clear-btn'/>");
						$clearBtn.on('click',function(e){
							$this.val("");
							$this.parent().find(".m-clear-btn").remove();
							$this.focus();
						});
						$this.after($clearBtn);
					}
					options.autocomplete && $this && handle($this,$this.val());
				} else {
					$this.parent().find(".m-clear-btn").remove();
					$this.parent().find(".m-drop-list").remove();
					$this.parent().find(".error-prompt").remove();
				}
			});
			$this.on("focus",function(e){
				removeDropList();
			});
			// 绑定点击事件
			$mTriggerBtn && $mTriggerBtn.on("click",function(e){
				$this && handle($this,$this.val());
			});
		},
		// 时间轴
		/*$(".m-timeline").timeline({
			"data":[],
			"contentDefine":{
				"id":"id",
				"time":"",
				"date":"",
				"content":""
			},
			// 定义你的内容主体，返回值可有可无，你可以考虑用$container去append你的内容，
			// 也可以让插件append你返回的内容，前提是你返回的必须是一个jquery对象
			"contentBody":function($container,item){
				$container.append($xxx);
				// var $content=...;
				// return $content;
			},
			"onError":function($container, errorText){return $xxx}
			
		});*/
		timeline:function(options){
			var $this = this;
			var contentDefine = options.contentDefine || {};
			var cssClass= options.cssClass;
			var data = options.data || [];
			// 输出列表内容
			var outputList = function(data){
				// 清空内容
				$this.find("ul.m-timeline").remove();
				$this.find('.error-prompt').remove();
				// 发送ajax请求，输出内容
				var $ul = $("<ul/>");
				$ul.addClass("m-timeline");
				cssClass && $ul.addClass(cssClass);
				$.each(data,function(index, item){
					var $li = $("<li/>");
					$li.attr({
						"data-id":(contentDefine.id ? item[contentDefine.id] : "")
					});
					var $timeWrapper = $("<div class='time-wrapper'/>");
					var $date = $("<time class='date'/>");
					contentDefine.date && $date.text(item[contentDefine.date]);
					$timeWrapper.append($date);
					var $time = $("<time class='time'/>");
					contentDefine.time && $time.text(item[contentDefine.time]);
					$timeWrapper.append($time);
					
					var $content = $("<div class='content'/>");
					contentDefine.content && $content.text(item[contentDefine.content]);
					
					if(options.contentBody && options.contentBody instanceof Function){
						var $contentBody = options.contentBody($content,item);
						$contentBody && $content.append($contentBody);
					}
					
					$li.append($timeWrapper);
					$li.append($content);
					
					$ul.append($li);
				});
				$this.append($ul);
				/*$ul.css("display","none");
				$ul.slideDown(200);*/
				$ul.focus();
			};
			// 移除错误提示
			var removeErrorContent = function() {
				$this.find('.timeline-error-container').remove();
			};
			// 输出错误内容
			var outputErrorContent = function(errorText){
				$this.find(".error-prompt").remove();
				$this.find('.m-timeline').remove();
				var $errorContent = $("<p></p>");
				if (options.onError) {
					$errorContent = $("<div class='timeline-error-container'/>");
					$errorContent = options.onError($errorContent, errorText);
				} else {
					$errorContent.addClass("error-prompt m-timeline-error-prompt");
					$errorContent.text(errorText);
				}
				$this.append($errorContent);
			};
			if(data && data.length > 0){
				removeErrorContent();
				outputList(data);
			} else {
				removeErrorContent();
				outputErrorContent("没有查询到内容");
			}
		},
		zuiLightBox:function(){
			var items = $(this);
			var topBody = MsgBox.getBody();
			var len = topBody.find("#lightboxModal").length;
			if(len == 0){
				appendLightBox();
			}
			$(items).bind("click",function(){
				var largeImg = $(this).attr("data-large-url");
				var content = $(this).attr("data-large-content");
				if(largeImg == null || largeImg == "" || largeImg.length == 0){
					largeImg = ctx+"/static-system/images/notFindPic.png";
					content = "未找到相应图片";
				}
				topBody.find("#lightboxModal .lightbox-img").attr('src',largeImg); 
				topBody.find("#lightboxModal .content").html(content);
				topBody.find('#lightboxModal').modal('show', 'center');
			});
			/*topBody.find("#lightboxModal .lightbox-img").click(function(e){
				e.stopPropagation();
				e.preventDefault();
			});*/
		},
		zuiLightBoxShow:function(){
			var largeImg = $(this).attr("data-large-url");
			var content = $(this).attr("data-large-content");
			if(largeImg == null || largeImg == "" || largeImg.length == 0){
				largeImg = ctx+"/static-system/images/notFindPic.png";
				content = "未找到相应图片";
			}
			var topBody = MsgBox.getBody();
			topBody.find("#lightboxModal .lightbox-img").attr('src',largeImg); 
			topBody.find("#lightboxModal .content").html(content);
			topBody.find('#lightboxModal').modal('show', 'center');
		},
		/**
		 * jquery plugins
		 * @功能：文本溢出时修饰
		 * @作者：lj
		 * @日期：20170516
		 */
//		 $(".xo").overTexts({
//            texts: '特别长的文本内容',
//            textLength: "40",  // 显示展开/收缩的最大字符长度
//            overText: "展开",
//            openText: "收起",
//            ooType: "2" // ooType:
						  //   1: 显示展开，不显示收缩
						  //   2: 显示展开和收缩
						  //   3: 显示省略号
//        });
		overTexts: function(options) {
			var t1;
			var $this = $(this);
            var dft = {
                //初始化的参数配置
                texts: "",
                textLength: "20",
                overText: "展开",
                openText: "收起",
                ooType: "2"
            };
            // 可能$this已经包含text，而没赋值给options.texts
            if (!options.texts) {
            	options.texts = $this.text();
            }
            // 直接装文本
            var buildCommonStateDiv = function(text, ignoreText) {
            	var $moreTextDiv = $("<p class='moreText'/>");
            	$moreTextDiv.attr({
            		'title': opt.texts
            	});
            	!ignoreText && $moreTextDiv.text(text);
            	return $moreTextDiv;
            };
            // 获取展开收起状态的DIV，带有收起超链接
            var buildPackupStateDiv = function(text) {
            	var $moreTextDiv = buildCommonStateDiv(text, true);
            	var $text = $("<span class='t-text'/>");
            	var $a = $("<a class='moreoh'/>");
                $a.text(opt.overText);
                $text.text(text);
                $moreTextDiv.append($text);
                $moreTextDiv.append($a);
                // 绑定展开事件
                $a.off('click').on('click', function(){
                	onSpread($(this));
                });
                return $moreTextDiv;
            };
            // 获取内容带省略号的DIV，没有展开/收起超链接
            var buildEllipsisDiv = function(text) {
            	var $moreTextDiv = buildCommonStateDiv(text, true);
            	text += "...";
            	$moreTextDiv.text(text);
            	return $moreTextDiv;
            };
            // 申明点击展开收起按钮的事件方法
            var onSpread = function($a) {
            	if ($a.text() == opt.overText) {//如果我此时是展开
                    if (opt.ooType == 2) {
                        t1 = opt.texts;
                        $a.text(opt.openText);
                        $a.closest(".moreText").find(".t-text").text(t1);
                    } else {
                        t1 = opt.texts;
                        $a.closest(".moreText").find(".t-text").text(t1);
                        $a.remove();
                    }
                } else if ($a.text() == opt.openText) {//如果我此时是收起
                    t1 = opt.texts.substring(0, opt.textLength);
                    $a.text(opt.overText);
                    $a.closest(".moreText").find(".t-text").text(t1);
                }
            };
            // 没有赋值的，保持默认
            var opt = $.extend(dft, options);
            if (opt.ooType == '1' || opt.ooType == '2') {
            	var $moreTextDiv = null;
                if (opt.texts.length > opt.textLength) {
                    t1 = opt.texts.substring(0, opt.textLength);
                    $moreTextDiv = buildPackupStateDiv(t1); // 超出textLength，显示展开超链接
                } else {
                    t1 = opt.texts;
                    $moreTextDiv = buildCommonStateDiv(t1); // 文本未超出textLength，直接显示
                }
                $this.replaceWith($moreTextDiv);
            }
            if (opt.ooType == '3') {
            	var $moreTextDiv = null;
                if (opt.texts.length > opt.textLength) {
                    t1 = opt.texts.substring(0, opt.textLength);
                    $moreTextDiv = buildEllipsisDiv(t1);
                } else {
                    t1 = opt.texts;
                    $moreTextDiv = buildCommonStateDiv(t1);
                }
                $this.replaceWith($moreTextDiv);
            }
		},
		/**
		 * jquery plugins
		 * @功能：文本强调
		 * @作者：lj
		 * @日期：20170517
		 */
		highlight:function(options) {
			var opt = {
				'className': 'm-highlight',
				'timeout': 1000
			};
			opt = $.extend(opt, options);
			var $this = this;
			this.addClass(opt.className);
			setTimeout(function(){
				$this.removeClass(opt.className);
			}, opt.timeout);
		},
		/**
		 * jquery plugins
		 * $('#xx').fixedPrompt().warn('警告信息', {
		 *     'showIcon':true/false,
		 *     'showCloseBtn':true/false
		 * })
		 * @功能：固定位置的消息提示
		 * @作者：lj
		 * @日期：2017-05-18
		 */
		fixedPrompt: function(){
			var $this = this;
			return {
				warn: function(msg, options) {this._show(msg, 'warn', options);},
				info: function(msg, options) {this._show(msg, 'info', options);},
				error:function(msg,options){this._show(msg, 'error', options);},
				success:function(msg,options){this._show(msg, 'success', options);},
				clear:function() {
					$this.hide({
						'speed':'300',
						'callback':function(){
							$this.empty();
						}
					});
				},
				_show:function(msg,type,options){
					var opt = {
						'showIcon': false,
						'showCloseBtn':true
					};
					$this.css({
						'display':'none'
					});
					opt = $.extend(opt, options);
					$this.empty();
					var FIXED_PROMPT_CONSTANTS = {
						'warn': {
							'className': 'alert-warning',
							'icon': 'icon-frown'
						},
						'info': {
							'className': 'alert-info',
							'icon': 'icon-info-sign'
						},
						'error': {
							'className': 'alert-danger',
							'icon': 'icon-remove-sign'
						},
						'success': {
							'className': 'alert-warning',
							'icon': 'icon-frown'
						}
					};
					var $alert = $("<div class='alert with-icon alert-dismissable'/>");
					$alert.addClass(FIXED_PROMPT_CONSTANTS[type]['className']);
					var $button = $("<button type='button' class='close' data-dismiss='alert' aria-hidden='true'>×</button>");
					var $content = $("<div class='content'/>");
					$content.text(msg);
					if (opt.showIcon) {
						var $icon = $("<i/>");
						$icon.addClass(FIXED_PROMPT_CONSTANTS[type]['icon']);
						$alert.append($icon);
						$alert.append($content);
						opt.showCloseBtn && $alert.append($button);
					} else {
						opt.showCloseBtn && $alert.append($button);
						$alert.append($content);
					}
					$this.append($alert);
					$this.show({
						'speed': '300',
						'easing': 'linear'
					});
				}
			};
		},
		/**
		 * jquery plugins
		 * $('#xx').readonlyFrmInput()
		 * @功能：表单只读
		 * @作者：lj
		 * @日期：2017-05-22
		 */
		readonlyFrmInput:function(readonly){
			if (readonly || readonly==undefined) {
				var setting = {
					'readonly':'readonly'
				};
				this.find('input[name]').attr(setting);
				this.find('select[name]').attr(setting);
				this.find('select[name]').attr({
					'disabled':'disabled'
				});
				this.find('textarea[name]').attr(setting);
			}
		},
		/**
		 * jquery plugins
		 * $('#xx').allowEditFrmInput()
		 * @功能：允许表单可编辑
		 * @作者：lj
		 * @日期：2017-05-22
		 */
		allowEditFrmInput:function(){
			this.find("input[name][readonly='readonly']").removeAttr('readonly');
			this.find("select[name][readonly='readonly']").removeAttr('readonly');
			this.find("textarea[name][readonly='readonly']").removeAttr('readonly');
			this.find("input[name][readonly='readonly']").removeAttr('disabled');
			this.find("select[name][readonly='readonly']").removeAttr('disabled');
			this.find("textarea[name][readonly='readonly']").removeAttr('disabled');
		},
		simpleValidate: function(	) {
			var $this = this;
			var val = this.val();
			if (StringUtil.isBlank(val)) {
				MsgBox.warn(emptyText, null, function(){
					$this.focus();
				});
				return false;
			}
			var validate = ValidateUtil[validateFuncName](val);
			if (!validate) {
				MsgBox.warn(errorText, null, function() {
					$this.focus();
				});
				return false;
			}
			return true;
		},
		/**
		 * jquery plugins
		 * $('#xx').dropSelectList({})
		 * @属性：<p>id,name,className,
		 * showSelectAll,showSelectName,showSelectValue,
		 * readonly,defaultValue,onSelected,silent
		 * contentDefine{textKey,valueKey}
		 * url,onSuccess</p>
		 * @功能：下拉菜单
		 * @作者：lj
		 * @日期：2017-05-31
		 * @调用：dropList.tag
		 */
		dropSelectList:function(options) {
			this.empty();
			
			var opt = {
				'silent':false
			};
			opt = $.extend(opt, options);
			var $that = this;
			
			// 用于构造select的mOpt
			var mOpt = {};
			mOpt = $.extend(mOpt, opt);
			
			var contentDefine = opt.contentDefine;
			$.mAjax({
				'url':opt.url,
				'type':'get',
				'dataType':'json',
				'contentType':'application/x-www-form-urlencoded',
				'silent':opt.silent,
				'success':function(data, status, xhr) {
					ObjectUtil.isFunction(opt.onSuccess) && opt.onSuccess(data, status, xhr);
					
					var arr = new Array();
					if (ArrayUtil.hasData(data.info)) {
						$.each(data.info, function(index, item) {
							arr.push({
								'text':item[contentDefine.textKey],
								'value':item[contentDefine.valueKey],
							});
						});
					}
					
					mOpt.data = arr;
					var $select = $._buildSelect(mOpt);
					$that.append($select);
				}
			});
		},
		/**
		 * jquery plugins
		 * @功能：构造加载中状态
		 * @参数：
		 * <p>iconSize,</p>
		 * @作者：lj
		 * @日期：2017-06-02 
		 * @调用：tree.tag
		 */
		startLoading:function(options) {
			var LOADER_ID = 'loader';
			var $loader = this.find('#' + LOADER_ID);
			if ($loader.length <= 0) {
				var opt = {
					'iconSize':3
				};
				opt = $.extend(opt, options);
				$loader = $("<div/>");
				$loader.attr({
					'id':LOADER_ID,
					'class':'m-loader'
				});
				var $icon = $('<i/>');
				$icon.attr('class','icon icon-spin icon-spinner-indicator');
				$icon.addClass('icon-' + opt.iconSize + 'x');
				$loader.append($icon);
				this.append($loader);
			}
		},
		stopLoading:function(options) {
			var LOADER_ID = 'loader';
			var $loader = this.find('#' + LOADER_ID);
			$loader.remove();
		},
		/**
		 * jquery plugins
		 * @功能：列出标签块
		 * @参数：
		 * <p>contentDefine{text,id},edit,remove,view,data,onRemove(e,item),onEdit(e,item),onView(e,item),emptyText,afterBuild,beforeBuild,css{border}</p>
		 * @作者：lj
		 * @日期：2017-06-02 
		 */
		listTags:function(options) {
			this.empty();
			var opt = {
				'edit':false,
				'remove':false,
				'view':false,
				'contentDefine':{
					'id':'id',
					'text':'text'
				},
				'emptyText':'没有数据',
				'css':{
					'border':'1px solid #EEE'
				}
			};
			$.extend(opt,options);
			var contentDefine = opt.contentDefine;
			var css = opt.css;
			var that = this;
			var ICON_SET = {
				'edit':'icon icon-edit',
				'view':'icon icon-eye-open',
				'remove':'icon icon-times'
			};
			// 记录所有标签
			opt.allTagInfos = new GenericSet(opt.data);
			var recorder = new Recorder();
			
			var $container = $("<div class='m-tags'/>");
			$container.css(css);
			opt.beforeBuild && opt.beforeBuild(this);
			// 方法申明 - 构造tag项
			var buildTagItem = function(item) {
				var $tag = $("<a class='m-tag'/>");
				$tag.attr({
					'data-id':item[contentDefine.id],
					'data-text':item[contentDefine.text]
				});
				$tag.text(item[contentDefine.text]);
				if (opt.edit) {
					var $icon = $("<i/>").addClass(ICON_SET['edit']);
					$icon.on('click',function(e){
						opt.onEdit && opt.onEdit(e, item);
					});
					$tag.append($icon);
				}
				if (opt.remove) {
					var $icon = $("<i/>").addClass(ICON_SET['remove']);
					$icon.on('click',function(e){
						$tag.remove();
						opt.onRemove && opt.onRemove(e, item);
					});
					$tag.append($icon);
				}
				if (opt.view) {
					var $icon = $("<i/>").addClass(ICON_SET['view']);
					$icon.on('click',function(e){
						opt.onView && opt.onView(e, item);
					});
					$tag.append($icon);
				}
				return $tag;
			};
			// 方法申明 - 构造内容为空时的标签
			var buildEmptyText = function() {
				var $empty = $("<p class='m-empty-text'></p>");
				if (ObjectUtil.isFunction(opt.emptyText)) {
					$empty.append(opt.emptyText());
				} else {
					$empty.text(opt.emptyText);
				}
				return $empty;
			};
			
			// 具体业务流程
			if (ArrayUtil.hasData(opt.data)) {
				$.each(opt.data, function(index, item) {
					var $tag = buildTagItem(item);
					$container.append($tag);
				});
			} else {
				$container.append(buildEmptyText());
			}
			that.append($container);
			opt.afterBuild && opt.afterBuild(this);
			return {
				// 判断是否存在用户操作
				'hasOperate':function() {
					return recorder.hasOperate();
				},
				'getRecorder':function(){
					return recorder;
				},
				'getAllTagInfos':function() {
					return opt.allTagInfos.arr;
				},
				// item:要新增的数据，key:用于对象数组中做比较的字段，func:当opt.allTagInfos中已存在item时的回调
				'addItem':function(item, key, func) {
					key = key || contentDefine.id;
					if (!opt.allTagInfos.hasData()) {
						$container.find('.m-empty-text').remove();
					}
					if (!opt.allTagInfos.hasItemOfKey(item, key)) {
						var $tag = buildTagItem(item);
						$tag.highlight({
							'timeout':500
						});
						$container.append($tag);
					} else {
						func && func();
					}
					this.getRecorder().getNewRecords().putByKey(item, key);
					opt.allTagInfos.putByKey(item, key);
				},
				// item:要删除的数据，key:用于对象数组中做比较的字段，func:当删除到为空时的回调
				'deleteItem':function(item, key,func) {
					key = key || contentDefine.id;
					this.getRecorder().getDeleteRecords().putByKey(item, key);
					opt.allTagInfos.removeByKey(item, key);
					if (!opt.allTagInfos.hasData()) {
						$container.append(buildEmptyText());
						func && func();
					}
				},
				'updateItem':function(item, key) {
					key = key || contentDefine.id;
					this.getRecorder().getUpdateRecords().putByKey(item, key);
					opt.allTagInfos.putByKey(item, key);
				}
			};
		},
		/**
		 * @功能 根据datatable表格中的元素定位数据并返回
		 * @参数 datatable
		 * @作者 lj 
		 * @日期 20170615
		 */
		getDatatableCurrentData:function(datatable) {
			var rowNum = this.closest("tr").data("index");
			return datatable.records[rowNum].data;
		},
		/**
		 * @功能 输出菜单
		 * @参数 {onMenuItemClick(value, text, url, level),contentDefine{children,value,text,url},data}
		 * @作者 lj 
		 * @日期 20170718
		 */
		menusx:function(options) {
			ObjectUtil.cleanup(options);
			var opt = {
				'contentDefine':{
					'children':'children',
					'value':'value',
					'text':'text',
					'url':'url'
				}
			};
			opt = $.extend(opt, options);
			// 输出内容
			this.empty();
			if(!options.data){
				console.log("menus没有数据可输出");
				return ;
			}
			// 删除菜单
			var removeChildMenu = function(e, $li) {
				$li.find('ul').remove();
			};
			
			// 输出菜单
			var outputMenu = function(list, $dom, level, opt){
				var $ul = $("<ul></ul>");
				// 通过data-level属性 + CSS样式控制不同层级菜单的样式
				$ul.attr({
					"data-level":level
				});
				$.each(list,function(index,item){
					var $li = $("<li></li>");
					var $a = $("<a></a>");
					$a.attr({
						"data-value":item[opt.contentDefine.value],
						"data-text":item[opt.contentDefine.text],
						"data-url":item[opt.contentDefine.url]
					});
					$a.text(item[opt.contentDefine.text]);
					$li.append($a);
					var children = item[opt.contentDefine.children];
					// 绑定点击事件 
					$a.off("mouseenter").on("mouseenter", function(e){
						var len = $li.find("ul").length;
						if(len >= 1){
							return ;
						}
						if(children && children.length > 0){
							outputMenu(children, $li, level+1, opt);
						}
						$li.find("ul").off("mouseleave").on("mouseleave", function(e){
							removeChildMenu(e, $li);
						});
						var width = parseInt($a.css("width"));
						$a.off("mouseleave").on("mouseleave",function(e){
							if(e.offsetX <= 0 || e.offsetX >= width){
								removeChildMenu(e, $li);
							}
							if(e.offsetY <= 0) {
								removeChildMenu(e, $li);
							}
						});
					});
					$a.off('click').on('click', function(e) {
						var value = $(this).data("value");
						var text = $(this).data("text");
						var url = $(this).data("url");
						var level = $(this).closest("ul").data("url");
						opt.onMenuItemClick && opt.onMenuItemClick(value, text, url, level);
					});
					$ul.append($li);
				});
				$dom.append($ul);
			};
			outputMenu(opt.data, this, 1, opt);
		}
		
	});
})(window.jQuery);
function appendLightBox(){//margin-top: 64.5px;
	var html = '<div id="lightboxModal" tabindex="-1" role="dialog" aria-hidden="true" data-appendToBody="true"'+ 
		'data-dialog="true" style="display: none;top:40px;vertical-align: middle;" '+
		'class="modal modal-trigger fade modal-lightbox in lightbox-with-caption" aria-hidden="true">'+
		'<div class="icon-spinner icon-spin loader"></div>'+
		'<div class="modal-dialog" style="width: 800px;max-height:600px; margin-top: 64.5px;">'+
			'<button class="close" data-dismiss="modal" aria-hidden="true">'+
				'<i class="icon-remove"></i>'+
			'</button>'+
			'<img class="lightbox-img" style="max-width:100%;min-width:600px;max-height:600px;min-height:500px;" src="" alt="" data-dismiss="modal">'+
			'<div class="caption">'+
				'<div class="content" style="text-align:center"></div>'+
			'</div>'+
		'</div>'+
	'</div>';
	MsgBox.getBody().append(html);
}
//取消按钮的enter事件
$(this).keydown( function(e) {
    var key = window.event?e.keyCode:e.which;
    if(key.toString() == "13"){
        return false;
    }
});

